一、線程池是什么
一般來說,線程池是一種池化技術(shù)的實(shí)現(xiàn)主慰,通過一個(gè)或者多個(gè)線程來執(zhí)行用戶提交的任務(wù),解決了每執(zhí)行一個(gè)任務(wù)就創(chuàng)建一個(gè)線程造成的資源浪費(fèi)問題鲫售,同時(shí)也提供了很多對線程進(jìn)行管理的操作方法共螺,比如停止一個(gè)線程或者統(tǒng)計(jì)已經(jīng)完成的任務(wù)量等等。
-
類結(jié)構(gòu)
image.png
從類的結(jié)構(gòu)圖中看到情竹,ThreadPoolExecutor實(shí)現(xiàn)了Executor以及ExecutorService的接口
1藐不、Executor:Executor提供了execute()接口,ThreadPoolExecutor對其進(jìn)行了實(shí)現(xiàn)
2秦效、ExecutorService:ExecutorService定義了shutdown()雏蛮、submit()等接口,主要作用是對線程池狀態(tài)的控制以及定義任務(wù)提交的方式
3阱州、AbstractExecutorService:AbstractExecuorService是模板方法設(shè)計(jì)模式的實(shí)現(xiàn)挑秉,提供了ExecutorService接口的默認(rèn)實(shí)現(xiàn),提供線程池通用的邏輯能力苔货,比如submit()方法
二犀概、類參數(shù)
-
阻塞隊(duì)列
-
ArrayBlockingQueue
image.png -
LinkedBlockingQueue
image.png -
DelayQueue
image.png -
SynchronousQueue
可以簡單的理解為:如果要往隊(duì)列放元素必須要有另一個(gè)線程想從隊(duì)列中取元素鹊汛,沒有現(xiàn)場要取你就放不進(jìn)去
image.png -
TransferQueue
TransferQueue可以理解為SynchronousQueue的加強(qiáng)版,比如公平鎖阱冶,按請求先后順序進(jìn)行處理
image.png -
PriorityBlockingQueue
image.png
-
拒絕策略
- DiscardOldestPolicy 丟棄隊(duì)列中第一個(gè)任務(wù)
- AbortPolicy 拋異常
- CallerRunsPolicy 交給提交過來的線程去執(zhí)行
- DiscardPolicy 丟棄,不做任何操作
三滥嘴、線程池類型
newCachedThreadPool:創(chuàng)建一個(gè)可緩存線程池木蹬,如果線程池長度超過處理所需,可靈活回收空閑線程若皱,若線程數(shù)不夠镊叁,則新建線程。
newFixedThreadPool:創(chuàng)建一個(gè)固定大小的線程池走触』奁可控制并發(fā)的線程數(shù)量,如果工作線程數(shù)量達(dá)到線程池初始的最大數(shù)互广,則將提交的任務(wù)存入到池隊(duì)列中敛腌。
newSingleThreadExecutor:創(chuàng)建一個(gè)單線程的線程池,即只創(chuàng)建唯一的工作者線程來執(zhí)行任務(wù)惫皱,像樊,保證所有任務(wù)按照指定順序(FIFO, LIFO, 優(yōu)先級)執(zhí)行。
-
newScheduleThreadPool:創(chuàng)建一個(gè)定長的線程池旅敷,支持定時(shí)及周期性任務(wù)執(zhí)行生棍。
image.png
四、踩坑經(jīng)歷
- 工作中媳谁,很多小伙伴使用newCachedThreadPool新建線程池涂滴,這個(gè)線程池的最大線程數(shù)是Integer.Max值,正常情況下晴音,是會導(dǎo)致線程池線程太多柔纵,耗盡服務(wù)器資源導(dǎo)致性能問題,所以使用時(shí)考慮清楚
- newFixedThreadPool锤躁,任務(wù)隊(duì)列大小可達(dá)Integer.Max首量,正常情況任務(wù)堆積過多絕對導(dǎo)致OOM,已經(jīng)目測過兩次
- 如果線程池中的任務(wù)隊(duì)列大小在業(yè)務(wù)發(fā)展過程中不會很大进苍,可以使用線程池加缘,不過一般我建議使用MQ,原因有兩個(gè):一是如果發(fā)生重啟或者服務(wù)器宕機(jī)觉啊,隊(duì)列中的任務(wù)就會丟失拣宏,二是很難控制隊(duì)列中的任務(wù)不會過大,而MQ會自動幫我們保存消息