根據阿里巴巴開發手冊:
我們線程池使用ThreadPoolExecutor的方式進行創建,下面看底層源碼:
有七個參數:
現在創建它:核心線程數2,同時執行的最大線程數5,多餘線程存活時間1L,單位秒,阻塞隊列3,默認線程工廠,拒絕策略
創建線程池:
第一種拒絕策略:AbortPolicy:超出最大線程數,直接拋出RejectedExecutionException異常阻止系統正常運行。
運行五個線程:
運行八個線程:
運行9個線程:
由此可以看出最大線程數爲:同時執行的最大線程數+任務隊列(阻塞隊列)數,超過了最大線程數直接運行拒絕策略。
第二種拒絕策略:
“調用者運行”一種調節機制,該策略既不會拋棄任務,也不會拋出異常,而是將某些任務回退到調用者,從而降低新任務的流量。(誰調用了你,到達最大線程數時,你回去找調用你的人,然後聽從調用你的人安排)(超出的我們能辦的給你辦,不能辦的給你回退 )
第三拒絕策略:DiscardOldestPolicy:拋棄隊列中等待最久的任務,然後把當前任務加入隊列中嘗試再次提交當前任務
第四種拒絕策略:DiscardPolicy:直接丟棄任務,不予任何處理也不拋異常,如果允許任務丟失這是最好的一種方案。
線程池配置合理線程數
查看機器的核心數
------------------------
CPU密集型:cpu的核數+1,這樣可以儘量減少切換
IO密集型:cpu的核數*10(一般阻塞系統是0.9)
業務場景:
1:高併發、任務執行時間短的業務,線程池線程數可以設置爲CPU核數+1,減少線程上下文的切換
2:併發不高、任務執行時間長的業務這就需要區分開看了:
a)假如是業務時間長集中在IO操作上,也就是IO密集型的任務,因爲IO操作並不佔用CPU,所以不要讓所有的CPU閒下來,可以適當加大線程池中的線程數目,讓CPU處理更多的業務
b)假如是業務時間長集中在計算操作上,也就是計算密集型任務,這個就沒辦法了,和(1)一樣吧,線程池中的線程數設置得少一些,減少線程上下文的切換
(其實從一二可以看出無論併發高不高,對於業務中是否是cpu密集還是I/O密集的判斷都是需要的當前前提是你需要優化性能的前提下)
3:併發高、業務執行時間長,解決這種類型任務的關鍵不在於線程池而在於整體架構的設計,看看這些業務裏面某些數據是否能做緩存是第一步,我們的項目使用的時redis作爲緩存(這類非關係型數據庫還是挺好的)。增加服務器是第二步(一般政府項目的首先,因爲不用對項目技術做大改動,求一個穩,但前提是資金充足),至於線程池的設置,設置參考 2 。最後,業務執行時間長的問題,也可能需要分析一下,看看能不能使用中間件(任務時間過長的可以考慮拆分邏輯放入隊列等操作)對任務進行拆分和解耦。