合適的線程數量是多少?CPU 核心數和線程數的關系?


 
你可能經常在面試中被問到這兩個問題。合適的線程數量是多少?CPU 核心數和線程數的關系?
我們調整線程池中的線程數量的最主要的目的是為了 充分並合理地使用 CPU 和內存等資源,從而最大限度地提高程序的性能。
在實際工作中,我們需要根據任務類型的不同選擇對應的策略。
 

CPU 密集型任務

首先,我們來看 CPU 密集型任務,比如:加密、解密、壓縮、計算等一系列需要大量耗費 CPU 資源的任務。

對於這樣的任務最佳的線程數為 CPU 核心數的 1~2 倍,如果設置過多的線程數,實際上並不會起到很好的效果。

  此時假設我們設置的線程數量是 CPU 核心數的 > 2 倍,因為計算任務非常重,會占用大量的 CPU 資源,所以這時 CPU 的每個核心工作基本都是滿負荷的,而我們又設置了過多的線程,每個線程都想去利用 CPU 資源來執行自己的任務,這就會造成不必要的上下文切換,此時線程數的增多並沒有讓性能提升,反而由於線程數量過多會導致性能下降。

針對這種情況,我們最好還要同時考慮在同一台機器上還有哪些其他會占用過多 CPU 資源的程序在運行,然后對資源使用做整體的平衡。

 

耗時 IO 型任務    

第二種任務是耗時 IO 型,比如:數據庫、文件的讀寫,網絡通信等任務,這種任務的特點是並不會特別消耗 CPU 資源,但是 IO 操作很耗時,總體會占用比較多的時間。

對於這種任務最大線程數一般會大於 CPU 核心數很多倍,因為 IO 讀寫速度相比於 CPU 的速度而言是比較慢的,如果我們設置過少的線程數,就可能導致 CPU 資源的浪費。

而如果我們設置更多的線程數,那么當一部分線程正在等待 IO 的時候,它們此時並不需要 CPU 來計算,那么另外的線程便可以利用 CPU 去執行其他的任務,互不影響,這樣的話在任務隊列中等待的任務就會減少,可以更好地利用資源。

 

《Java並發編程實戰》的作者 Brain Goetz 推薦的計算方法:

線程數 = CPU 核心數 *(1+平均等待時間/平均工作時間)

通過這個公式,我們可以計算出一個合理的線程數量,如果任務的平均等待時間長,線程數就隨之增加,而如果平均工作時間長,也就是對於我們上面的 CPU 密集型任務,線程數就隨之減少。

 

太少的線程數會使得程序整體性能降低,而過多的線程也會消耗內存等其他資源,

所以如果想要更准確的話,可以進行壓測,監控 JVM 的線程情況以及 CPU 的負載情況,根據實際情況衡量應該創建的線程數,合理並充分利用資源。

使用JDK 自帶的工具 VisualVM 來查看線程等待時間和線程工作時間。
 

 

結論

綜上所述我們就可以得出一個結論:

  • 線程的平均工作時間所占比例越高,就需要越少的線程;

  • 線程的平均等待時間所占比例越高,就需要越多的線程;

  • 針對不同的程序,進行對應的實際測試就可以得到最合適的選擇。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM