1. 程式人生 > 其它 >多個場景共用一個大的執行緒池還是每個任務單獨使用執行緒池

多個場景共用一個大的執行緒池還是每個任務單獨使用執行緒池

1.首先,專案中如果有多個場景需要使用執行緒池,那麼最好的方式是:每一個業務場景使用獨立的執行緒池。不要讓所有的場景共用一個執行緒池。

分析:

1)獨立的線城池之間互相不影響彼此的任務作業,更有利於保證本任務的獨立性和完整性,更符合低耦合的設計思想

2)如果所有的場景共用一個執行緒池,可能會出現如下問題,舉例:

比如有任務A、任務B、任務C 這三個任務場景共用一個執行緒池,配置如下

threadPool:
  corePoolSize: 20
  maximumPoolSize: 2000
  workQueue: 1000
  keepAliveSeconds: 300
  • 第1個引數 :corePoolSize 表示常駐核心執行緒數。如果等於0,則任務執行完成後,沒有任何請求進入時銷燬執行緒池的執行緒;如果大於0,即使本地任務執行完畢,核心執行緒也不會被銷燬。這個值的設定非常關鍵,設定過大會浪費資源,設定的過小會導致執行緒頻繁地建立或銷燬。
  • 第2個引數:maximumPoolSize 表示執行緒池能夠容納同時執行的最大執行緒數。從上方的示例程式碼中第一處來看,必須大於或等於1。如果待執行的執行緒數大於此值,需要藉助第5個引數的幫助。快取在佇列中。如果maximumPoolSize 與corePoolSize 相等,即是固定大小執行緒池。
  • 第3個引數:workQueue 表示快取佇列。如果執行緒池裡的執行緒數大於corePoolSize ,就會放到快取佇列,快取佇列滿了會建立新執行緒到maximumPoolsize;直到當請求的執行緒數大於maximumPoolSize時,會執行設定的策略,預設是拒絕建立策略。(注意:當執行緒池裡的執行緒數大於corePoolSize且小於maximumPoolSize時,這時候再有請求的執行緒就會放到快取佇列,注意只是放到快取佇列但是不建立新的執行緒
    ,直到請求的執行緒存滿快取佇列時,才會開始建立新的執行緒,直到maxmunPoolSize就會拒絕建立或者執行提前設定的策略。
  • 第4個引數:keepAliveSeconds
    表示執行緒池中的執行緒空閒時間,當空閒時間達到keepAliveSeconds值時,執行緒被銷燬,直到剩下corePoolSize 個執行緒為止,避免浪費記憶體和控制代碼資源。在預設情況下,當執行緒池的執行緒大於corePoolSize 時,keepAliveSeconds才會起作用。但是ThreadPoolExecutor的allowCoreThreadTimeOut 變數設定為ture時,核心執行緒超時後也會被回收。

當任務A請求量劇烈增加的時候就會導致任務B和任務C,沒有可用的執行緒 可能出現遲遲獲取不到資源的情況。比如任務A同時有3000個執行緒請求,此時就可能會導致 任務B和任務C分配不到資源或者分配到很少的執行緒資源。

所以為了避免這種情況的產生,最好的方式是建立獨立的執行緒池。

這樣不管任務A的執行緒是堵塞還是其他原因,都不會影響任務B和任務C,同理任務B、任務C也一樣不會影響其他場景任務的執行。

2.注:

1.JDK自帶的類使用了很多的執行緒池.
2.很多開源框架使用了大量的執行緒池.
3.自己的應用也會建立多個執行緒池.
4.不要在意什麼CPU密集還是IO密集(這是一種人云亦云的說法,至少java語言來說不要考慮什麼IO還是CPU).
5.多少個執行緒池,每個執行緒池提供多少執行緒,必須經過詳細的測試,不能人云亦云,不能參考別人.
不同的業務,不同的場景,執行緒池的個數,執行緒的數量都是不一樣的.

一臺伺服器硬體資源是固定的,比如20核心40執行緒的CPU,能部署一個應用,就儘量部署一個,不要什麼都部署.

經過測試你會發現:

有時候執行緒建立多了會消耗大量的記憶體,關鍵是無法提升效能.
當你建立1個執行緒,5執行緒,10執行緒時,處理資料的效能差不多,那就不應該建立多個.
所以,執行緒池相關的問題,需要經過長時間的測試,不斷的測試最終提供一套符合目前需求的引數.