1. 程式人生 > >執行緒池執行緒數量優化設計

執行緒池執行緒數量優化設計

實際編碼過程中,不能一味的只進行執行緒池優化效能而不關注具體的設計細節。執行緒池執行緒數量需要根據實際專案中任務數量等進行一個估算,使得系統的設計效能趨近於我們所想的方向,而不是隨便給一個數值,但是不進行系統的最大瓶頸的控制。

廢話不多說:轉個比較詳細的效能估算思路:

JDK1.5中引入了強大的concurrent包,其中最常用的莫過了執行緒池的實現ThreadPoolExecutor,它給我們帶來了極大的方便,但同時,對於該執行緒池不恰當的設定也可能使其效率並不能達到預期的效果,甚至僅相當於或低於單執行緒的效率。

ThreadPoolExecutor類可設定的引數主要有:

  • corePoolSize

核心執行緒數,核心執行緒會一直存活,即使沒有任務需要處理。當執行緒數小於核心執行緒數時,即使現有的執行緒空閒,執行緒池也會優先建立新執行緒來處理任務,而不是直接交給現有的執行緒處理。

核心執行緒在allowCoreThreadTimeout被設定為true時會超時退出,預設情況下不會退出。

  • maxPoolSize
當執行緒數大於或等於核心執行緒,且任務佇列已滿時,執行緒池會建立新的執行緒,直到執行緒數量達到maxPoolSize。如果執行緒數已等於maxPoolSize,且任務佇列已滿,則已超出執行緒池的處理能力,執行緒池會拒絕處理任務而丟擲異常。
  • keepAliveTime

當執行緒空閒時間達到keepAliveTime,該執行緒會退出,直到執行緒數量等於corePoolSize。如果allowCoreThreadTimeout設定為true,則所有執行緒均會退出直到執行緒數量為0。

  • allowCoreThreadTimeout

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

  • queueCapacity

任務佇列容量。從maxPoolSize的描述上可以看出,任務佇列的容量會影響到執行緒的變化,因此任務佇列的長度也需要恰當的設定。

執行緒池按以下行為執行任務

  1. 當執行緒數小於核心執行緒數時,建立執行緒。
  2. 當執行緒數大於等於核心執行緒數,且任務佇列未滿時,將任務放入任務佇列。
  3. 當執行緒數大於等於核心執行緒數,且任務佇列已滿
    1. 若執行緒數小於最大執行緒數,建立執行緒
    2. 若執行緒數等於最大執行緒數,丟擲異常,拒絕任務

系統負載

引數的設定跟系統的負載有直接的關係,下面為系統負載的相關引數:

  • tasks,每秒需要處理的最大任務數量
  • tasktime,處理第個任務所需要的時間
  • responsetime,系統允許任務最大的響應時間,比如每個任務的響應時間不得超過2秒。

引數設定

corePoolSize:

每個任務需要tasktime秒處理,則每個執行緒每鈔可處理1/tasktime個任務。系統每秒有tasks個任務需要處理,則需要的執行緒數為:tasks/(1/tasktime),即tasks*tasktime個執行緒數。假設系統每秒任務數為100~1000,每個任務耗時0.1秒,則需要100*0.1至1000*0.1,即10~100個執行緒。那麼corePoolSize應該設定為大於10,具體數字最好根據8020原則,即80%情況下系統每秒任務數,若系統80%的情況下第秒任務數小於200,最多時為1000,則corePoolSize可設定為20。

queueCapacity:

任務佇列的長度要根據核心執行緒數,以及系統對任務響應時間的要求有關。佇列長度可以設定為(corePoolSize/tasktime)*responsetime: (20/0.1)*2=400,即佇列長度可設定為400。

佇列長度設定過大,會導致任務響應時間過長,切忌以下寫法:

LinkedBlockingQueue queue = new LinkedBlockingQueue();

這實際上是將佇列長度設定為Integer.MAX_VALUE,將會導致執行緒數量永遠為corePoolSize,再也不會增加,當任務數量陡增時,任務響應時間也將隨之陡增。

maxPoolSize:

當系統負載達到最大值時,核心執行緒數已無法按時處理完所有任務,這時就需要增加執行緒。每秒200個任務需要20個執行緒,那麼當每秒達到1000個任務時,則需要(1000-queueCapacity)*(20/200),即60個執行緒,可將maxPoolSize設定為60。

keepAliveTime:

執行緒數量只增加不減少也不行。當負載降低時,可減少執行緒數量,如果一個執行緒空閒時間達到keepAliveTiime,該執行緒就退出。預設情況下執行緒池最少會保持corePoolSize個執行緒。

allowCoreThreadTimeout:

預設情況下核心執行緒不會退出,可通過將該引數設定為true,讓核心執行緒也退出。

以上關於執行緒數量的計算並沒有考慮CPU的情況。若結合CPU的情況,比如,當執行緒數量達到50時,CPU達到100%,則將maxPoolSize設定為60也不合適,此時若系統負載長時間維持在每秒1000個任務,則超出執行緒池處理能力,應設法降低每個任務的處理時間(tasktime)。


轉自:http://blog.csdn.net/zhouhl_cn/article/details/7392607