1. 程式人生 > >ThreadPoolExecutor執行緒池大小設定

ThreadPoolExecutor執行緒池大小設定

最近用到ThreadPoolExecutor ,想到這個問題;
下面是從網上找到的。

執行緒池的理想大小取決於被提交任務的型別以及所部署系統的特性。執行緒池應該避免設定的過大或過小,如果執行緒池過大,大量的執行緒將在相對很少的CPU和記憶體資源上發生競爭,這不僅會導致更高的記憶體使用量,而且還可能耗盡資源。如果執行緒池過小,那麼將導致許多空閒處理器無法執行任務,降低了系統吞吐率。

要想合理的配置執行緒池的大小,首先得分析任務的特性,可以從以下幾個角度分析:

任務的性質:CPU密集型任務、IO密集型任務、混合型任務。
任務的優先順序:高、中、低。
任務的執行時間:長、中、短。
任務的依賴性:是否依賴其他系統資源,如資料庫連線等。

性質不同的任務可以交給不同規模的執行緒池執行。

對於不同性質的任務來說,CPU密集型任務應配置儘可能小的執行緒,如配置CPU個數+1的執行緒數,IO密集型任務應配置儘可能多的執行緒,因為IO操作不佔用CPU,不要讓CPU閒下來,應加大執行緒數量,如配置兩倍CPU個數+1,而對於混合型的任務,如果可以拆分,拆分成IO密集型和CPU密集型分別處理,前提是兩者執行的時間是差不多的,如果處理時間相差很大,則沒必要拆分了。

若任務對其他系統資源有依賴,如某個任務依賴資料庫的連線返回的結果,這時候等待的時間越長,則CPU空閒的時間越長,那麼執行緒數量應設定得越大,才能更好的利用CPU。
當然具體合理執行緒池值大小,需要結合系統實際情況,在大量的嘗試下比較才能得出,以上只是前人總結的規律。

在這篇如何合理地估算執行緒池大小?有一個估算合理值的公式

最佳執行緒數目 = ((執行緒等待時間+執行緒CPU時間)/執行緒CPU時間 )* CPU數目

比如平均每個執行緒CPU執行時間為0.5s,而執行緒等待時間(非CPU執行時間,比如IO)為1.5s,CPU核心數為8,那麼根據上面這個公式估算得到:((0.5+1.5)/0.5)*8=32。這個公式進一步轉化為:

最佳執行緒數目 = (執行緒等待時間與執行緒CPU時間之比 + 1)* CPU數目

可以得出一個結論:
執行緒等待時間所佔比例越高,需要越多執行緒。執行緒CPU時間所佔比例越高,需要越少執行緒。
以上公式與之前的CPU和IO密集型任務設定執行緒數基本吻合。

併發程式設計網上的一個問題
高併發、任務執行時間短的業務怎樣使用執行緒池?併發不高、任務執行時間長的業務怎樣使用執行緒池?併發高、業務執行時間長的業務怎樣使用執行緒池?
(1)高併發、任務執行時間短的業務,執行緒池執行緒數可以設定為CPU核數+1,減少執行緒上下文的切換

(2)併發不高、任務執行時間長的業務要區分開看:
  a)假如是業務時間長集中在IO操作上,也就是IO密集型的任務,因為IO操作並不佔用CPU,所以不要讓所有的CPU閒下來,可以適當加大執行緒池中的執行緒數目,讓CPU處理更多的業務
  b)假如是業務時間長集中在計算操作上,也就是計算密集型任務,這個就沒辦法了,和(1)一樣吧,執行緒池中的執行緒數設定得少一些,減少執行緒上下文的切換
  
(3)併發高、業務執行時間長,解決這種型別任務的關鍵不在於執行緒池而在於整體架構的設計,看看這些業務裡面某些資料是否能做快取是第一步,增加伺服器是第二步,至於執行緒池的設定,設定參考(2)。最後,業務執行時間長的問題,也可能需要分析一下,看看能不能使用中介軟體對任務進行拆分和解耦