一、線程池是什么
一般來說,線程池是一種池化技術的實現(xiàn),通過一個或者多個線程來執(zhí)行用戶提交的任務,解決了每執(zhí)行一個任務就創(chuàng)建一個線程造成的資源浪費問題,同時也提供了很多對線程進行管理的操作方法,比如停止一個線程或者統(tǒng)計已經(jīng)完成的任務量等等。
-
類結構
image.png
從類的結構圖中看到,ThreadPoolExecutor實現(xiàn)了Executor以及ExecutorService的接口
1、Executor:Executor提供了execute()接口,ThreadPoolExecutor對其進行了實現(xiàn)
2、ExecutorService:ExecutorService定義了shutdown()、submit()等接口,主要作用是對線程池狀態(tài)的控制以及定義任務提交的方式
3、AbstractExecutorService:AbstractExecuorService是模板方法設計模式的實現(xiàn),提供了ExecutorService接口的默認實現(xiàn),提供線程池通用的邏輯能力,比如submit()方法
二、類參數(shù)

-
阻塞隊列

-
ArrayBlockingQueue
image.png -
LinkedBlockingQueue
image.png -
DelayQueue
image.png -
SynchronousQueue
可以簡單的理解為:如果要往隊列放元素必須要有另一個線程想從隊列中取元素,沒有現(xiàn)場要取你就放不進去
image.png -
TransferQueue
TransferQueue可以理解為SynchronousQueue的加強版,比如公平鎖,按請求先后順序進行處理
image.png -
PriorityBlockingQueue
image.png
-
拒絕策略

- DiscardOldestPolicy 丟棄隊列中第一個任務
- AbortPolicy 拋異常
- CallerRunsPolicy 交給提交過來的線程去執(zhí)行
- DiscardPolicy 丟棄,不做任何操作
三、線程池類型
newCachedThreadPool:創(chuàng)建一個可緩存線程池,如果線程池長度超過處理所需,可靈活回收空閑線程,若線程數(shù)不夠,則新建線程。
newFixedThreadPool:創(chuàng)建一個固定大小的線程池??煽刂撇l(fā)的線程數(shù)量,如果工作線程數(shù)量達到線程池初始的最大數(shù),則將提交的任務存入到池隊列中。
newSingleThreadExecutor:創(chuàng)建一個單線程的線程池,即只創(chuàng)建唯一的工作者線程來執(zhí)行任務,,保證所有任務按照指定順序(FIFO, LIFO, 優(yōu)先級)執(zhí)行。
-
newScheduleThreadPool:創(chuàng)建一個定長的線程池,支持定時及周期性任務執(zhí)行。
image.png
四、踩坑經(jīng)歷
- 工作中,很多小伙伴使用newCachedThreadPool新建線程池,這個線程池的最大線程數(shù)是Integer.Max值,正常情況下,是會導致線程池線程太多,耗盡服務器資源導致性能問題,所以使用時考慮清楚
- newFixedThreadPool,任務隊列大小可達Integer.Max,正常情況任務堆積過多絕對導致OOM,已經(jīng)目測過兩次
- 如果線程池中的任務隊列大小在業(yè)務發(fā)展過程中不會很大,可以使用線程池,不過一般我建議使用MQ,原因有兩個:一是如果發(fā)生重啟或者服務器宕機,隊列中的任務就會丟失,二是很難控制隊列中的任務不會過大,而MQ會自動幫我們保存消息







