線程池隊列大小設(shè)置?
一、ThreadPoolExecutor的重要參數(shù)
corePoolSize:核心線程數(shù), 核心線程會一直存活,及時沒有任務(wù)需要執(zhí)行,當(dāng)線程數(shù)小于核心線程數(shù)時,即使有線程空閑,線程池也會優(yōu)先創(chuàng)建新線程處理,設(shè)置allowCoreThreadTimeout=true(默認false)時,核心線程會超時關(guān)閉
queueCapacity:任務(wù)隊列容量(阻塞隊列)
當(dāng)核心線程數(shù)達到最大時,新任務(wù)會放在隊列中排隊等待執(zhí)行
maxPoolSize:最大線程數(shù)
當(dāng)線程數(shù)>=corePoolSize,且任務(wù)隊列已滿時。線程池會創(chuàng)建新線程來處理任務(wù)
當(dāng)線程數(shù)=maxPoolSize,且任務(wù)隊列已滿時,線程池會拒絕處理任務(wù)而拋出異常
keepAliveTime:線程空閑時間
當(dāng)線程空閑時間達到keepAliveTime時,線程會退出,直到線程數(shù)量=corePoolSize
如果allowCoreThreadTimeout=true,則會直到線程數(shù)量=0
allowCoreThreadTimeout:允許核心線程超時
rejectedExecutionHandler:任務(wù)拒絕處理器
兩種情況會拒絕處理任務(wù):
當(dāng)線程數(shù)已經(jīng)達到maxPoolSize,切隊列已滿,會拒絕新任務(wù)
當(dāng)線程池被調(diào)用shutdown()后,會等待線程池里的任務(wù)執(zhí)行完畢,再shutdown。如果在調(diào)用shutdown()和線程池真正shutdown之間提交任務(wù),會拒絕新任務(wù)
線程池會調(diào)用rejectedExecutionHandler來處理這個任務(wù)。如果沒有設(shè)置默認是 AbortPolicy,會拋出異常
ThreadPoolExecutor類有幾個內(nèi)部實現(xiàn)類來處理這類情況:
AbortPolicy 丟棄任務(wù),拋運行時異常
CallerRunsPolicy 執(zhí)行任務(wù)
DiscardPolicy 忽視,什么都不會發(fā)生
DiscardOldestPolicy 從隊列中踢出最先進入隊列(最后一個執(zhí)行)的任務(wù)
實現(xiàn)RejectedExecutionHandler接口,可自定義處理器
二、ThreadPoolExecutor執(zhí)行順序
線程池按以下行為執(zhí)行任務(wù)
(1)當(dāng)線程數(shù)小于核心線程數(shù)時,創(chuàng)建線程。
(2)當(dāng)線程數(shù)大于等于核心線程數(shù),且任務(wù)隊列未滿時,將任務(wù)放入任務(wù)隊列。
(3)當(dāng)線程數(shù)大于等于核心線程數(shù),且任務(wù)隊列已滿
1)若線程數(shù)小于最大線程數(shù),創(chuàng)建線程
2)若線程數(shù)等于最大線程數(shù),拋出異常,拒絕任務(wù)
三、如何設(shè)置參數(shù)
默認值
corePoolSize=1
queueCapacity=Integer.MAX_VALUE
maxPoolSize=Integer.MAX_VALUE
keepAliveTime=60s
allowCoreThreadTimeout=false
rejectedExecutionHandler=AbortPolicy()
如何來設(shè)置
需要根據(jù)幾個值來決定
tasks :每秒的任務(wù)數(shù),假設(shè)為500~1000
taskcost:每個任務(wù)花費時間,假設(shè)為0.1s
responsetime:系統(tǒng)允許容忍的最大響應(yīng)時間,假設(shè)為1s
做幾個計算
corePoolSize = 每秒需要多少個線程處理?
threadcount = tasks/(1/taskcost) =tasks*taskcout = (500~1000)*0.1 = 50~100 個線程。corePoolSize設(shè)置應(yīng)該大于50
根據(jù)8020原則,如果80%的每秒任務(wù)數(shù)小于800,那么corePoolSize設(shè)置為80即可
queueCapacity = (coreSizePool/taskcost)*responsetime
計算可得 queueCapacity = 80/0.1*1 = 80。意思是隊列里的線程可以等待1s,超過了的需要新開線程來執(zhí)行
切記不能設(shè)置為Integer.MAX_VALUE,這樣隊列會很大,線程數(shù)只會保持在corePoolSize大小,當(dāng)任務(wù)陡增時,不能新開線程來執(zhí)行,響應(yīng)時間會隨之陡增。
maxPoolSize = (max(tasks)- queueCapacity)/(1/taskcost)
計算可得 maxPoolSize = (1000-80)/10 = 92
(最大任務(wù)數(shù)-隊列容量)/每個線程每秒處理能力 = 最大線程數(shù)
rejectedExecutionHandler:根據(jù)具體情況來決定,任務(wù)不重要可丟棄,任務(wù)重要則要利用一些緩沖機制來處理
keepAliveTime和allowCoreThreadTimeout采用默認通常能滿足
以上都是理想值,實際情況下要根據(jù)機器性能來決定。如果在未達到最大線程數(shù)的情況機器cpu load已經(jīng)滿了,則需要通過升級硬件和優(yōu)化代碼,降低taskcost來處理。