多線程 - 如何合理配置線程池


總結

根據“任務的性質”分析

CPU 密集型任務

  • 和內存打交道,大量計算。例如大數的計算,正則匹配
  • 如何配置:
    • CPU 密集型任務應配置盡可能小的線程,如配置 Ncpu+1 個線程的線程池(Ncpu 是處理器的核的數目),這樣留一個空出來,用來做切換。。
    • 如果線程太多,會造成線程在CPU內部的上下文切換。。CPU的線程上下文切換比指令執行耗時的更多。

IO 密集型任務

  • 解釋:和磁盤,網絡,文件,數據庫交互很多的。
  • 如何配置:由於 IO 密集型任務線程並不是一直在執行任務,在操作的時間,是不消耗CPU的。不會經常在CPU內切換線程上下文,則應配置盡可能多的線程,如 2*Ncpu。
    • 對於 IO 型的任務的最佳線程數,有個公式可以計算 Nthreads = NCPU * UCPU * (1 + W/C)

      ❑NCPU 是處理器的核的數目

      ❑UCPU 是期望的 CPU 利用率(該值應該介於 0 和 1 之間)

      ❑W/C 是等待時間與計算時間的比率。等待時間與計算時間我們在 Linux 下使用相關的 vmstat 命令或者 top 命令查看。

混合型任務

  • 解釋:前兩者的混合
  • 如何配置:如果可以拆分,將其拆分成一個 CPU 密集型任務和一個 IO 密集型任務。
    • 只要這兩個任務執行的時間相差不是太大,那么分解后執行的吞吐 量將高於串行執行的吞吐量。
    • 如果這兩個任務執行時間相差太大(例如:一個是常量時間,一個是正無窮),則沒必要進行分解。
    • 可以通過 Runtime.getRuntime().availableProcessors()方法獲得當前設備的 CPU 個數。

 

 

根據“任務的優先級”分析

優先級不同的任務可以使用優先級隊列 PriorityBlockingQueue 來處理。它可 以讓優先級高的任務先執行。

 

根據“任務的執行時間”分析

執行時間不同的任務可以交給不同規模的線程池來處理,或者可以使用優先 級隊列,讓執行時間短的任務先執行。

 

根據“任務的依賴性(依賴數據庫連接)”分析

依賴數據庫連接池的任務,因為線程􏰀交 SQL 后需要等待數據庫返回結果, 等待的時間越長,則 CPU 空閑時間就越長,那么線程數應該設置得越大,這樣 才能更好地利用 CPU。

 

建議使用有界隊列

有界隊列能增加系統的穩定性和預警能力,可以根據需 要設大一點兒,比如幾千。

假設,我們現在有一個 Web 系統,里面使用了線程池來處理業務,在某些 情況下,系統里后台任務線程池的隊列和線程池全滿了,不斷拋出拋棄任務的異 常,通過排查發現是數據庫出現了問題,導致執行 SQL 變得非常緩慢,因為后台 任務線程池里的任務全是需要向數據庫查詢和插入數據的,所以導致線程池里的 工作線程全部阻塞,任務積壓在線程池里。

如果當時我們設置成無界隊列,那么線程池的隊列就會越來越多,有可能會 撐滿內存,導致整個系統不可用,而不只是后台任務出現問題。

 


免責聲明!

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



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