作者:林冠宏 / 指尖下的幽靈
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
它用來處理延時或定時任務,不常用