作者:林冠巨集 / 指尖下的幽靈
掘金:https://juejin.im/user/587f0dfe128fe100570ce2d8
部落格:http://www.cnblogs.com/linguanh/
GitHub : https://github.com/af913337456/
有時候花了大把時間去看一些東西卻看不懂,是很 “ 藍瘦 ” 的,花時間也是投資。
本文適合:
- 曾瞭解過執行緒池卻一直模模糊糊的人
- 瞭解得差不多卻對某些點依然疑惑的
不適合:
- 完全沒看過的,建議你先去看看其他基礎文章
- 看過,卻忘得差不多了,建議你先去回顧下
本文能給你的閱讀回報
- 適合的讀者,儘可能讓你徹底明白
常用的執行緒池
的知識相關點 - 不適合的讀者,能有個不錯的概念,神童另談
廢話少說,我們開始。下圖,皆可自行儲存,常常閱之。日久,根深蒂固
預設建構函式
public ThreadPoolExecutor(
int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue,
ThreadFactory threadFactory,
RejectedExecutionHandler handler
)
{
....
}
複製程式碼
絕對易懂的構造方法引數講解
引數名 | 作用 |
---|---|
corePoolSize | 佇列沒滿時,執行緒最大併發數 |
maximumPoolSizes | 佇列滿後執行緒能夠達到的最大併發數 |
keepAliveTime | 空閒執行緒過多久被回收的時間限制 |
unit | keepAliveTime 的時間單位 |
workQueue | 阻塞的佇列型別 |
RejectedExecutionHandler | 超出 maximumPoolSizes + workQueue 時,任務會交給RejectedExecutionHandler來處理 |
文字描述
corePoolSize,maximumPoolSize,workQueue之間關係。
-
當執行緒池中執行緒數小於corePoolSize時,新提交任務將建立一個新執行緒執行任務,即使此時執行緒池中存在空閒執行緒。
-
當執行緒池中執行緒數達到corePoolSize時,新提交任務將被放入workQueue中,等待執行緒池中任務排程執行 。
-
當workQueue已滿,且maximumPoolSize > corePoolSize時,新提交任務會建立新執行緒執行任務。
-
當workQueue已滿,且提交任務數超過maximumPoolSize,任務由RejectedExecutionHandler處理。
-
當執行緒池中執行緒數超過corePoolSize,且超過這部分的空閒時間達到keepAliveTime時,回收這些執行緒。
-
當設定allowCoreThreadTimeOut(true)時,執行緒池中corePoolSize範圍內的執行緒空閒時間達到keepAliveTime也將回收。
一般流程圖
newFixedThreadPool 流程圖
public static ExecutorService newFixedThreadPool(int nThreads){
return new ThreadPoolExecutor(
nThreads, // corePoolSize
nThreads, // maximumPoolSize == corePoolSize
0L, // 空閒時間限制是 0
TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>() // 無界阻塞佇列
);
}
複製程式碼
newCacheThreadPool 流程圖
public static ExecutorService newCachedThreadPool(){
return new ThreadPoolExecutor(
0, // corePoolSoze == 0
Integer.MAX_VALUE, // maximumPoolSize 非常大
60L, // 空閒判定是60 秒
TimeUnit.SECONDS,
// 神奇的無儲存空間阻塞佇列,每個 put 必須要等待一個 take
new SynchronousQueue<Runnable>()
);
}
複製程式碼
newSingleThreadPool 流程圖
public static ExecutorService newSingleThreadExecutor() {
return
new FinalizableDelegatedExecutorService
(
new ThreadPoolExecutor
(
1,
1,
0L,
TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>(),
threadFactory
)
);
}
複製程式碼
可以看到除了多了個 FinalizableDelegatedExecutorService
代理,其初始化和 newFiexdThreadPool
的 nThreads = 1 的時候是一樣的。
區別就在於:
- newSingleThreadExecutor返回的ExcutorService在解構函式finalize()處會呼叫shutdown()
- 如果我們沒有對它呼叫shutdown(),那麼可以確保它在被回收時呼叫shutdown()來終止執行緒。
使用ThreadFactory
,可以改變執行緒的名稱、執行緒組、優先順序、守護程式狀態,一般採用預設。
流程圖略,請參考 newFiexdThreadPool,這裡不再累贅。
最後
還有一個定時任務執行緒池ScheduledThreadPool
它用來處理延時或定時任務,不常用