ThreadPoolExecutor執行緒池的keepAliveTime

沉默的背影發表於2019-05-29

keepAliveTime含義

看了很多文章覺得都不能把keepAliveTime的意思說的很明白,希望通過自己的理解把keepAliveTime說的明確一些

先引用一句我覺得相對說的比較明白的含義:當執行緒空閒時間達到keepAliveTime,該執行緒會退出,有兩個疑問:1、執行緒為什麼會空閒 2、執行緒為什麼要退出

如果我們不能把執行緒池各個引數的來龍去脈都梳理清楚其實是很難明白keepAliveTime的含義的

我們來舉例說明:

核心執行緒數10,最大執行緒數30,keepAliveTime是3秒

隨著任務數量不斷上升,執行緒池會不斷的建立執行緒,直到到達核心執行緒數10,就不建立執行緒了,

這時多餘的任務通過加入阻塞佇列來執行,

當超出阻塞佇列長度+核心執行緒數時,

這時不得不擴大執行緒個數來滿足當前任務的執行,這時就需要建立新的執行緒了(最大執行緒數起作用),上限是最大執行緒數30

那麼超出核心執行緒數10並小於最大執行緒數30的可能新建立的這20個執行緒相當於是“借”的,如果這20個執行緒空閒時間超過keepAliveTime,就會被退出

我們來看開頭提到的兩個問題:

1、執行緒為什麼會空閒

2、執行緒為什麼要退出

答:

1、沒有任務時執行緒就會空閒下來,線上程池中任務是任務(Runnale)執行緒是執行緒(Worker)

2、通常超出核心執行緒的執行緒是“借”的,也就是說超出核心執行緒的情況算是一種能夠預見的異常情況,並且這種情況並不常常發生(如果常常發生,那我想你應該調整你的核心執行緒數了),所以這種不經常發生而建立的執行緒為了避免資源浪費就應該要退出

我們需要看一下java.util.concurrent.ThreadPoolExecutor#getTask原始碼來驗證上面一段話的含義:

int wc = workerCountOf(c);
// Are workers subject to culling? 是否屠宰workers
//當allowCoreThreadTimeOut為true或者當前任務數超過核心執行緒數時,timed為true
boolean timed = allowCoreThreadTimeOut || wc > corePoolSize;
……
try {
Runnable r = timed ?
workQueue.poll(keepAliveTime, TimeUnit.NANOSECONDS) ://如果timed為true說明worker有可能要被關閉,這裡呼叫的程式碼含義:如果超過keepAliveTime納秒還沒取到任務,就返回null,後面會呼叫processWorkerExit把worker關閉
workQueue.take();//否則任務佇列為空就阻塞在這裡,直到任務佇列再有任務
if (r != null)
return r;

10個核心執行緒會不會退出,由下面的引數決定:

allowCoreThreadTimeout:是否允許核心執行緒空閒退出,預設值為false

當keepAliveTime設定為0時到底是空閒執行緒直接退出還是不退出

通過實驗證明和上文程式碼workQueue.poll(keepAliveTime, TimeUnit.NANOSECONDS)證明,是直接不等待退出,而不是永遠不退出

這樣我們就需要注意了,這個值設定為0 並不是個很好的做法(除非場景中任務數量極少能超出核心執行緒數),如果任務數頻繁超出核心執行緒數,這個值需要評估設定為合理值儘量避免執行緒開啟關閉的動作

(上圖,如果永遠不退出,那麼workers就不是10 而是45)

 

相關文章