此文參考博客編寫.
1.什么是線程池
線程池就是若干個(gè)線程的集合,這些線程被池化了,能夠執(zhí)行多個(gè)任務(wù).而并非只為執(zhí)行一次任務(wù)而創(chuàng)建,也并非執(zhí)行完任務(wù)就銷毀.
2.線程池的實(shí)現(xiàn)原理
上述提到的若干個(gè)線程,我們稱之為工作線程. 一個(gè)線程池中通常有個(gè)定量的阻塞隊(duì)列queue與其配合使用
,當(dāng)外部向一個(gè)線程池提交一個(gè)任務(wù)時(shí),線程池會將這個(gè)任務(wù)放置到queue中,而線程池中的工作線程會不斷向queue中取出任務(wù)執(zhí)行.執(zhí)行完之后如果發(fā)現(xiàn)queue不為空,則繼續(xù)取,如果queue已經(jīng)為空, 工作線程們進(jìn)入waiting狀態(tài). 待queue再次不會空,這些線程會被喚醒.從而進(jìn)行下一次任務(wù)的執(zhí)行.大概原理就是這樣
3.線程池如何使用
看看JDK為我們提供的ThreadPoolExecutor.
我們可通過ThreadPoolExecutor來創(chuàng)建一個(gè)線程池.再調(diào)用其execute方法,傳入我們的任務(wù)Runable對象即可.
- 參數(shù)
-
int corePoolSize
基本工作線程數(shù)量 -
int maximumPoolSize
最大工作線程數(shù)量 -
long keepAliveTime
默認(rèn)全部工作線程除去基本工作線程的線程空閑時(shí)間.也可設(shè)置為所有線程的空閑時(shí)間. 一旦空閑時(shí)間超過了設(shè)定值,工作線程將被銷毀. -
TimeUnit unit
描述上個(gè)參數(shù)的單位. -
BlockingQueue<Runnable> workQueue
存放任務(wù)的阻塞隊(duì)列 -
ThreadFactory threadFactory
作用是根據(jù)任務(wù)Runable對象來生產(chǎn)工作線程中的線程. 比如可以對生成的線程設(shè)置名字等屬性. -
RejectedExecutionHandler handler
如果任務(wù)Runable對象被拒絕了,將會調(diào)用
handler.rejectedExecution(Runnable r, ThreadPoolExecutor executor)
你可以拋出異常或者選擇死亡
-
工作流程
流程圖
看完上述對參數(shù)比較口語化的描述.我們用他們來模擬一個(gè)ThreadPoolExecutor當(dāng)執(zhí)行execute方法是怎么干的
首先我們需要用一個(gè)Set<Worker>表示當(dāng)前我們持有的工作線程.
- 如果set的size比corePoolSize小,那就證明還沒有達(dá)到基本數(shù)量. 這個(gè)時(shí)候新建一個(gè)工作線程Worker來執(zhí)行Runable對象并將Worker放入set.
- 如果set的size已經(jīng)比corePoolSize大.那這個(gè)時(shí)候把Runable對象放入構(gòu)造函數(shù)傳進(jìn)來的BlockingQueue. 注意.此時(shí)調(diào)用的不是put方法,也不是add方法,是offer方法. offer方法特點(diǎn)就是如果隊(duì)列已滿就返回false.不等待也不拋異常,很老實(shí).. 如果放入成功,后續(xù)就會有工作線程來取走這個(gè)Runable對象.
放入Queue
- 如果放入失敗了. 那么判斷set的size是不是比maximumPoolSize 小. 如果小,新建一個(gè)工作線程Worker來執(zhí)行Runable對象.并將Worker放入set.
- 如果大,這個(gè)時(shí)候拒絕執(zhí)行Runable對象. 調(diào)用構(gòu)造函數(shù)傳入的RejectedExecutionHandler.rejectedExecution();
- ThreadPoolExecutor狀態(tài)
狀態(tài)流轉(zhuǎn)圖
- RUNNING
初始狀態(tài),接受新任務(wù)并且處理已經(jīng)在隊(duì)列中的任務(wù)。 - SHUTDOWN
不接受新任務(wù),但處理隊(duì)列中的任務(wù)。 - STOP
不接受新任務(wù),不處理排隊(duì)的任務(wù),并中斷正在進(jìn)行的任務(wù)。 - TIDYING
所有任務(wù)已終止,workerCount為零,線程轉(zhuǎn)換到狀態(tài)TIDYING,這時(shí)回調(diào)terminate()方法。 - TERMINATED
終態(tài),terminated()執(zhí)行完成。
4.線程池的意義
-
降低資源消耗
通過重復(fù)利用已創(chuàng)建的線程降低線程創(chuàng)建和銷毀的消耗 -
提高響應(yīng)速度
當(dāng)一個(gè)任務(wù)到達(dá)的時(shí)候,不必等待線程創(chuàng)建的時(shí)間就可以馬上執(zhí)行. -
提高線程的可管理性
線程是稀缺的資源,如果無限制地創(chuàng)建,會降低系統(tǒng)的穩(wěn)定性.使用線程可以進(jìn)行統(tǒng)一分配/調(diào)優(yōu)/監(jiān)控.