如何合理設定執行緒池大小

2021-10-01 18:21:21 字數 3194 閱讀 2204

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

任務的性質: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)。最後,業務執行時間長的問題,也可能需要分析一下,看看能不能使用中介軟體對任務進行拆分和解耦。

如何合理地估算執行緒池大小?

這個問題雖然看起來很小,卻並不那麼容易回答。大家如果有更好的方法歡迎賜教,先來乙個天真的估算方法:假設要求乙個系統的tps(transaction per second或者task per second)至少為20,然後假設每個transaction由乙個執行緒完成,繼續假設平均每個執行緒處理乙個transaction的時間為4s。那麼問題轉化為:

如何設計執行緒池大小,使得可以在1s內處理完20個transaction?

計算過程很簡單,每個執行緒的處理能力為0.25tps,那麼要達到20tps,顯然需要20/0.25=80個執行緒。

很顯然這個估算方法很天真,因為它沒有考慮到cpu數目。一般伺服器的cpu核數為16或者32,如果有80個執行緒,那麼肯定會帶來太多不必要的執行緒上下文切換開銷。

再來第二種簡單的但不知是否可行的方法(n為cpu總核數):

如果一台伺服器上只部署這乙個應用並且只有這乙個執行緒池,那麼這種估算或許合理,具體還需自行測試驗證。

接下來在這個文件:伺服器效能io優化 中發現乙個估算公式:

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

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

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

可以得出乙個結論:

執行緒等待時間所佔比例越高,需要越多執行緒。執行緒cpu時間所佔比例越高,需要越少執行緒。

上一種估算方法也和這個結論相合。

乙個系統最快的部分是cpu,所以決定乙個系統吞吐量上限的是cpu。增強cpu處理能力,可以提高系統吞吐量上限。但根據短板效應,真實的系統吞吐量並不能單純根據cpu來計算。那要提高系統吞吐量,就需要從「系統短板」(比如網路延遲、io)著手:

增強短板能力,比如用nio替代io

第一條可以聯絡到amdahl定律,這條定律定義了序列系統並行化後的加速比計算公式:

1加速比=優化前系統耗時 / 優化後系統耗時

加速比越大,表明系統並行化的優化效果越好。addahl定律還給出了系統並行度、cpu數目和加速比的關係,加速比為speedup,系統序列化比率(指序列執行**所佔比率)為f,cpu數目為n:

1speedup <=1/ (f + (1-f)/n)

當n足夠大時,序列化比率f越小,加速比speedup越大。

寫到這裡,我突然冒出乙個問題。

是否使用執行緒池就一定比使用單執行緒高效呢?

答案是否定的,比如redis就是單執行緒的,但它卻非常高效,基本操作都能達到十萬量級/s。從執行緒這個角度來看,部分原因在於:

當然「redis很快」更本質的原因在於:redis基本都是記憶體操作,這種情況下單執行緒可以很高效地利用cpu。而多執行緒適用場景一般是:存在相當比例的io和網路操作。

所以即使有上面的簡單估算方法,也許看似合理,但實際上也未必合理,都需要結合系統真實情況(比如是io密集型或者是cpu密集型或者是純記憶體操作)和硬體環境(cpu、記憶體、硬碟讀寫速度、網路狀況等)來不斷嘗試達到乙個符合實際的合理估算值。

如何合理設定執行緒池大小

要想合理的配置執行緒池的大小,首先得分析任務的特性,可以從以下幾個角度分析 任務的性質 cpu密集型任務 io密集型任務 混合型任務。任務的優先順序 高 中 低。任務的依賴性 是否依賴其他系統資源,如資料庫連線等。性質不同的任務可以交給不同規模的執行緒池執行。對於不同性質的任務來說,cpu密集型任務...

如何合理設定執行緒池大小

這個問題雖然看起來很小,卻並不那麼容易回答。大家如果有更好的方法歡迎賜教,先來乙個天真的估算方法 假設要求乙個系統的tps transaction per second或者task per second 至少為20,然後假設每個transaction由乙個執行緒完成,繼續假設平均每個執行緒處理乙個t...

java執行緒池如何合理的設定大小

任務一般分為 cpu密集型 io密集型 混合型,對於不同型別的任務需要分配不同大小的執行緒池 1 cpu密集型 盡量使用較小的執行緒池,一般cpu核心數 1 因為cpu密集型任務cpu的使用率很高,若開過多的執行緒,只能增加執行緒上下文的切換次數,帶來額外的開銷 2 io密集型 方法一 可以使用較大...