ThreadPoolExecutor線程池的keepAliveTime

keepAliveTime含義

看了不少文章以爲都不能把keepAliveTime的意思說的很明白,但願經過本身的理解把keepAliveTime說的明確一些java

先引用一句我以爲相對說的比較明白的含義:當線程空閒時間達到keepAliveTime,該線程會退出,有兩個疑問:一、線程爲何會空閒 二、線程爲何要退出spa

若是咱們不能把線程池各個參數的前因後果都梳理清楚實際上是很難明白keepAliveTime的含義的線程

咱們來舉例說明:code

核心線程數10,最大線程數30,keepAliveTime是3秒blog

隨着任務數量不斷上升,線程池會不斷的建立線程,直到到達核心線程數10,就不建立線程了,隊列

這時多餘的任務經過加入阻塞隊列來運行,資源

當超出阻塞隊列長度+核心線程數時,get

這時不得不擴大線程個數來知足當前任務的運行,這時就須要建立新的線程了(最大線程數起做用),上限是最大線程數30源碼

那麼超出核心線程數10並小於最大線程數30的可能新建立的這20個線程至關因而「借」的,若是這20個線程空閒時間超過keepAliveTime,就會被退出it

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

一、線程爲何會空閒

二、線程爲何要退出

答:

一、沒有任務時線程就會空閒下來,在線程池中任務是任務(Runnale)線程是線程(Worker)

二、一般超出核心線程的線程是「借」的,也就是說超出核心線程的狀況算是一種可以預見的異常狀況,而且這種狀況並不經常發生(若是經常發生,那我想你應該調整你的核心線程數了),因此這種不常常發生而建立的線程爲了不資源浪費就應該要退出

咱們須要看一下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)

相關文章
相關標籤/搜索