線程池能夠避免頻繁創(chuàng)建銷毀線程帶來的性能損耗玻佩,同時還維護(hù)了線程池的一些統(tǒng)計信息齿穗。
JDK中線程池的核心類是ThreadPoolExecutor,它的繼承鏈如下
ThreadPoolExecutor——>AbstractExecutorService——>ExecutorService——>Executor
Executor是一個只包含execute方法的接口,它的作用是將Task的提交和Task的執(zhí)行進(jìn)行解耦(Netty設(shè)計了自己的線程模型鞋喇,該接口在Netty中也大量使用)。
ExecutorService提供了Executor和Task(借助Futrue接口)的生命周期的管理函數(shù)眉撵。
下面侦香,主要看ThreadPoolExecutor這個類。
1.組成:
ThreadPoolExecutor包含一個BlockingQueue(workQueue)用于存儲任務(wù)纽疟,一個Set<Worker>(workers)用于存儲執(zhí)行任務(wù)的線程罐韩。
2.重要初始參數(shù):
(1)int?corePoolSize ?線程池核心線程數(shù)目
(2)int maximumPoolSize ?線程最大線程數(shù)目
默認(rèn)情況下,線程池初始化后污朽,是沒有線程的散吵,當(dāng)execute第一個任務(wù)時創(chuàng)建第一個Worker(即創(chuàng)建線程);當(dāng)線程數(shù)小于corePoolSize時蟆肆,不管有沒有空閑的線程矾睦,都會創(chuàng)建一個Worker并執(zhí)行該任務(wù);當(dāng)線程數(shù)大于等于corePoolSize時炎功,新來的任務(wù)會優(yōu)先加入到workQueue顷锰,當(dāng)workQueue滿的時候,才會新創(chuàng)建Work線程亡问,當(dāng)線程數(shù)目等于maximumPoolSize且workQueue滿的時候官紫,會采用RejectedExecutionHandler根據(jù)拒絕策略處理該任務(wù)。
(3)long keepAliveTime
大于corePoolSize的空閑線程的最大idle時間州藕,通過BlockingQueue的poll(long timeout, TimeUnit unit)實現(xiàn)束世。
(4)TimeUnit unit
(5)BlockingQueue workQueue
阻塞隊列,三種典型的選擇床玻,SynchronousQueue毁涉、LinkedBlockingQueue、ArrayBlockingQueue锈死。
SynchronousQueue:該隊列沒有容量只是在生產(chǎn)者消費者之間交換信息和任務(wù)贫堰,此情況下線程池maxsize通常無限制,但也要防止耗盡系統(tǒng)資源待牵。
LinkedBlockingQueue:無界的阻塞隊列其屏,maxsize失去作用,同樣可能會耗盡系統(tǒng)資源缨该。
ArrayBlockingQueue:queuesize和maxpoolsize要合理配置偎行,大的queuesize和小的maxpoolsize可以減少線程切換的損耗,但是可能會影響吞吐量,小的queuesize和大的maxpoolsize也可能會產(chǎn)生大量線程切換進(jìn)而影響吞吐量蛤袒。
(6)ThreadFactory threadFactory
為線程起名字熄云,利于日志分析。
(7)RejectedExecutionHandler
拒絕策略妙真,應(yīng)用了策略模式缴允,JDK實現(xiàn)了四種,1.拋出異常珍德,2.直接丟棄练般,3.刪除阻塞隊列中最老的task,4.添加任務(wù)的線程執(zhí)行該任務(wù)(進(jìn)而減慢生產(chǎn)者速度菱阵,達(dá)到調(diào)節(jié)作用)踢俄。
3.狀態(tài)
RUNNING: 接收新任務(wù)缩功,并處理阻塞隊列中的任務(wù)晴及;
SHUTDOWN: 不接收新任務(wù),但處理隊列中的任務(wù)嫡锌;
STOP: ? ?不接收新任務(wù)虑稼,不處理隊列中的任務(wù),并中斷所有正在執(zhí)行的任務(wù)势木;
TIDYING: ?所有任務(wù)都被蛛倦,worker數(shù)目為0,當(dāng)狀態(tài)變?yōu)門IDYING時啦桌,會執(zhí)行terminated()鉤子方法溯壶;
TERMINATED: terminated() 方法完成。
RUNNING -> SHUTDOWN: On invocation of shutdown(), perhaps implicitly in finalize()
(RUNNING or SHUTDOWN) -> STOP:On invocation of shutdownNow()
SHUTDOWN -> TIDYING:When both queue and pool are empty
STOP -> TIDYING:When pool is empty
TIDYING -> TERMINATED:When the terminated() hook method has completed
4.源碼分析
ThreadPoolExecutor的核心方法是execute方法甫男,其實現(xiàn)其實就是按照前面的執(zhí)行策略且改,建立線程(Worker),或者將任務(wù)添加到阻塞隊列板驳,或者將任務(wù)交給拒絕策略又跛。
添加Work的過程需要對mainLock加鎖(mainLock用于控制對Worker集合的訪問)。
Worker實現(xiàn)了Runnable接口若治,并繼承了AbstractQueuedSynchronizer類(實現(xiàn)了一個不可重入鎖慨蓝,作主要控制work線程的中斷,未啟動的線程不能中斷端幼,執(zhí)行shutdown方法時礼烈,先獲取該work的鎖才能中斷該線程),并且它是ThreadPoolExecutor的內(nèi)部類(這樣它就能訪問ThreadPoolExecutor的內(nèi)部變量和方法婆跑,在某種程度上可以說是實現(xiàn)了多繼承)济丘。它持有一個線程,一個Runnable即第一個執(zhí)行的任務(wù),以及一個long表示完成任務(wù)的數(shù)目摹迷。
Worker初始化的時候疟赊,state(AbstractQueuedSynchronizer的屬性)為-1,避免對為啟動的Work調(diào)用interrupt方法峡碉。
run方法執(zhí)行ThreadPoolExecutor的runWorker方法近哟,該方法首先獲得firstTask,并將其賦值為null使其得到回收鲫寄,接著在while循環(huán)中吉执,執(zhí)行第一個任務(wù),并不斷從阻塞隊列中獲取任務(wù)執(zhí)行地来,需要注意的是每次執(zhí)行任務(wù)前都要調(diào)用Work實例的加鎖方法戳玫,并檢查線程池的狀態(tài)(加鎖是防止shutdown時,殺死還在執(zhí)行任務(wù)的線程)未斑。
參考文章:
https://www.cnblogs.com/trust-freedom/p/6681948.html#label_3_3