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.多少個線程池,每個線程池提供多少線程,必須經過詳細的測試,不能人雲亦雲,不能參考別人.
不同的業務,不同的場景,線程池的個數,線程的數量都是不一樣的.
當你創建1個線程,5線程,10線程時,處理數據的性能差不多,那就不應該創建多個.
所以,線程池相關的問題,需要經過長時間的測試,不斷的測試最終提供一套符合目前需求的參數.
2.很多開源框架使用了大量的線程池.
3.自己的應用也會創建多個線程池.
4.不要在意什么CPU密集還是IO密集(這是一種人雲亦雲的說法,至少java語言來說不要考慮什么IO還是CPU).
5.多少個線程池,每個線程池提供多少線程,必須經過詳細的測試,不能人雲亦雲,不能參考別人.
不同的業務,不同的場景,線程池的個數,線程的數量都是不一樣的.
一台服務器硬件資源是固定的,比如20核心40線程的CPU,能部署一個應用,就盡量部署一個,不要什么都部署.
經過測試你會發現:
有時候線程創建多了會消耗大量的內存,關鍵是無法提升性能.當你創建1個線程,5線程,10線程時,處理數據的性能差不多,那就不應該創建多個.
所以,線程池相關的問題,需要經過長時間的測試,不斷的測試最終提供一套符合目前需求的參數.