Java線程池技術(shù)總結(jié)
四種內(nèi)置線程池
newSingleThreadExecutor
創(chuàng)建一個單線程的線程池获黔。這個線程池只有一個線程在工作,也就是相當(dāng)于單線程串行執(zhí)行所有任務(wù)在验。如果這個唯一的線程因為異常結(jié)束玷氏,那么會有一個新的線程來替代它。此線程池保證所有任務(wù)的執(zhí)行順序按照任務(wù)的提交順序執(zhí)行腋舌。
newFixedThreadPool
創(chuàng)建固定大小的線程池盏触。每次提交一個任務(wù)就創(chuàng)建一個線程,直到線程達(dá)到線程池的最大大小块饺。線程池的大小一旦達(dá)到最大值就會保持不變赞辩,如果某個線程因為執(zhí)行異常而結(jié)束,那么線程池會補(bǔ)充一個新線程授艰。
newCachedThreadPool
創(chuàng)建一個可緩存的線程池辨嗽。如果線程池的大小超過了處理任務(wù)所需要的線程,
那么就會回收部分空閑(60秒不執(zhí)行任務(wù))的線程淮腾,當(dāng)任務(wù)數(shù)增加時糟需,此線程池又可以智能的添加新線程來處理任務(wù)。此線程池不會對線程池大小做限制谷朝,線程池大小完全依賴于操作系統(tǒng)(或者說JVM)能夠創(chuàng)建的最大線程大小洲押。
newScheduledThreadPool
創(chuàng)建一個大小無限的線程池。此線程池支持定時以及周期性執(zhí)行任務(wù)的需求圆凰。
自定義線程池
完整的線程池定義如下:
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue,
RejectedExecutionHandler handler) {
this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
Executors.defaultThreadFactory(), handler);
}
參數(shù) | 含義 |
---|---|
corePoolSize | 線程池維護(hù)線程的最少數(shù)量 |
maximumPoolSize | 線程池維護(hù)線程的最大數(shù)量 |
keepAliveTime | 線程池維護(hù)線程所允許的空閑時間 |
unit | 線程池維護(hù)線程所允許的空閑時間的單位 |
workQueue | 線程池所使用的緩沖隊列 |
handler | 線程池對拒絕任務(wù)的處理策略 |
當(dāng)調(diào)用 execute()方法添加一個任務(wù)時杈帐,線程池會做如下判斷:
- 如果正在運行的線程數(shù)量小于corePoolSize,那么馬上創(chuàng)建線程運行這個任務(wù)专钉。
- 如果正在運行的線程數(shù)量大于或等于corePoolSize挑童,那么將這個任務(wù)放入隊列。
- 如果這時候隊列滿了跃须,而且正在運行的線程數(shù)量小于maximumPoolSize炮沐,那么還是要創(chuàng)建線程運行這個任務(wù)。
- 如果隊列滿了回怜,而且正在運行的線程數(shù)量大于或等于maximumPoolSize大年,那么線程池會拋出異常换薄,告訴調(diào)用者“我不能再接受任務(wù)了”。
四種拒絕處理策略
AbortPolicy
ThreadPoolExecutor.AbortPolicy() 拋出java.util.concurrent.RejectedExecutionException異常
CallerRunsPolicy
ThreadPoolExecutor.CallerRunsPolicy() 重試添加當(dāng)前的任務(wù)翔试,他會自動重復(fù)調(diào)用execute()方法
DiscardOldestPolicy
ThreadPoolExecutor.DiscardOldestPolicy() 拋棄舊的任務(wù)
DiscardPolicy
ThreadPoolExecutor.DiscardPolicy() 拋棄當(dāng)前的任務(wù)
三種隊列策略
SynchronousQueue
直接提交轻要。工作隊列的默認(rèn)選項是SynchronousQueue,它將任務(wù)直接提交給線程而不保持它們垦缅。在此冲泥,如果不存在可用于立即運行任務(wù)的線程,則試圖把任務(wù)加入隊列將失敗凡恍,因此會構(gòu)造一個新的線程怔球。此策略可以避免在處理可能具有內(nèi)部依賴性的請求集時出現(xiàn)鎖。直接提交通常要求無界 maximumPoolSizes 以避免拒絕新提交的任務(wù)闽巩。當(dāng)命令以超過隊列所能處理的平均數(shù)連續(xù)到達(dá)時担汤,此策略允許無界線程具有增長的可能性。
LinkedBlockingQueue
無界隊列隅很。使用無界隊列(例如率碾,不具有預(yù)定義容量的 LinkedBlockingQueue)將導(dǎo)致在所有 corePoolSize 線程都忙時新任務(wù)在隊列中等待。這樣审编,創(chuàng)建的線程就不會超過 corePoolSize歧匈。(因此砰嘁,maximumPoolSize 的值也就無效了。)當(dāng)每個任務(wù)完全獨立于其他任務(wù)矮湘,即任務(wù)執(zhí)行互不影響時,適合于使用無界隊列磕蛇;例如,在 Web 頁服務(wù)器中秀撇。這種排隊可用于處理瞬態(tài)突發(fā)請求,當(dāng)命令以超過隊列所能處理的平均數(shù)連續(xù)到達(dá)時棠绘,此策略允許無界線程具有增長的可能性再扭。
ArrayBlockingQueue
有界隊列。當(dāng)使用有限的 maximumPoolSizes 時让虐,有界隊列(如 ArrayBlockingQueue)有助于防止資源耗盡敦跌,但是可能較難調(diào)整和控制。隊列大小和最大池大小可能需要相互折衷:使用大型隊列和小型池可以最大限度地降低 CPU 使用率麸俘、操作系統(tǒng)資源和上下文切換開銷,但是可能導(dǎo)致人工降低吞吐量从媚。如果任務(wù)頻繁阻塞(例如患整,如果它們是 I/O 邊界),則系統(tǒng)可能為超過您許可的更多線程安排時間各谚。使用小型隊列通常要求較大的池大小,CPU 使用率較高昌渤,但是可能遇到不可接受的調(diào)度開銷,這樣也會降低吞吐量般眉。
未完潜支,待續(xù)