本文學(xué)習(xí)過(guò)程中持續(xù)更新
線程池的創(chuàng)建
為什么不推薦用 Executors
創(chuàng)建線程池炎码,而是用 ThreadPoolExecutor
的方式沼撕?
通過(guò) Executors
創(chuàng)建,以 FixedThreadPool
舉例
ExecutorService exec = Executors.newFixedThreadPool(thread_num)
public class Executors {
public static ExecutorService newFixedThreadPool(int nThreads) {
return new ThreadPoolExecutor(nThreads, nThreads,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>());
}
}
會(huì)創(chuàng)建一個(gè) ThreadPoolExecutor
在這里的構(gòu)造方法里愧薛,傳5個(gè)參數(shù)砰左,參數(shù)如下:
- corePoolSize: 除非設(shè)置了
允許核心線程超時(shí)的最大時(shí)間
,否則即使線程處于空閑狀態(tài)睡榆,也要保留在池中的線程數(shù) - maximumPoolSize: 線程池維護(hù)線程的最大數(shù)量
- keepAliveTime: 當(dāng)線程數(shù)大于核心時(shí)萍肆,這是多余空閑線程在終止之前等待新任務(wù)的最長(zhǎng)時(shí)間
- unit: 上述時(shí)間的單位
- workQueue: 在執(zhí)行任務(wù)之前用于保存任務(wù)的緩沖隊(duì)列袍榆,此隊(duì)列僅包含
excute
方法提交的Runnable
任務(wù)
當(dāng)然,這只是 ThreadPoolExecutor
的構(gòu)造方法之一塘揣,ThreadPoolExecutor
還有更多參數(shù)的構(gòu)造方法包雀,這里先不談。
再來(lái)到 excute
方法亲铡,該方法用于執(zhí)行提交的 Runnable
任務(wù)馏艾。
excute
的執(zhí)行邏輯大概如下:
- 當(dāng)池中線程數(shù)量少于
corePoolSize
,創(chuàng)建一個(gè)新線程去執(zhí)行任務(wù) - 當(dāng)池中線程數(shù)量等于
corePoolSize
奴愉,如果緩沖隊(duì)列workQueue
未滿琅摩,放入緩沖隊(duì)列 - 如果緩沖隊(duì)列滿,線程池?cái)?shù)量小于
maximumPoolSize
, 建新的線程來(lái)處理任務(wù) - 如果創(chuàng)建新的線程來(lái)處理任務(wù)失敗锭硼,說(shuō)明線程池?cái)?shù)量飽和房资,即達(dá)到了
maximumPoolSize
,會(huì)拒絕這次任務(wù)
在 ThreadPoolExecutor
中檀头,還有一個(gè) RejectedExecutionHandler
用來(lái)對(duì)拒絕的任務(wù)進(jìn)行處理轰异,這里先不談。
從 excute
的執(zhí)行方法中可以看到暑始,緩沖隊(duì)列也有個(gè)飽和值搭独,這個(gè)值是可以由我們自己設(shè)置的。
舉個(gè)例子廊镜,直接使用 ThreadPoolExecutor
創(chuàng)建的時(shí)候:
int count = 100;
ThreadPoolExecutor tp = new ThreadPoolExecutor(1, 1, 60, TimeUnit.SECONDS,
new LinkedBlockingDeque<>(count));
而上文中牙肝,用 Executors
創(chuàng)建 FixedThreadPool
:
ExecutorService exec = Executors.newFixedThreadPool(thread_num)
public class Executors {
public static ExecutorService newFixedThreadPool(int nThreads) {
return new ThreadPoolExecutor(nThreads, nThreads,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>());
}
}
這里的緩沖隊(duì)列初始化方法是這樣的:
/**
* Creates a {@code LinkedBlockingQueue} with a capacity of
* {@link Integer#MAX_VALUE}.
*/
public LinkedBlockingQueue() {
this(Integer.MAX_VALUE);
}
允許緩沖隊(duì)列的長(zhǎng)度為 Integer.MAX_VALUE
,這時(shí)可能會(huì)堆積大量的請(qǐng)求嗤朴,有OOM風(fēng)險(xiǎn)配椭。
創(chuàng)建 SingleThreadExecutor
與之同理,存在緩沖隊(duì)列堆積大量請(qǐng)求風(fēng)險(xiǎn)雹姊。
用 Executors
創(chuàng)建 CachedThreadPool
:
ExecutorService exec = Executors.newCachedThreadPool();
public static ExecutorService newCachedThreadPool() {
return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
60L, TimeUnit.SECONDS,
new SynchronousQueue<Runnable>());
}
允許創(chuàng)建的線程數(shù)量為 Integer.MAX_VALUE
股缸,會(huì)堆積大量的線程,有OOM風(fēng)險(xiǎn)吱雏。
創(chuàng)建 ScheduledThreadPool
與之同理敦姻,有堆積大量線程的風(fēng)險(xiǎn)。
所以推薦用 ThreadPoolExecutor
的方式創(chuàng)建線程池歧杏,手動(dòng)設(shè)置各種參數(shù)(包括最大線程數(shù)镰惦、緩沖隊(duì)列的最大長(zhǎng)度)。