前言
由于線程池涉及的知識(shí)點(diǎn)比較多,會(huì)以上中下三篇文章來敘述;
當(dāng)我們面試時(shí),如果遇到了面試官讓你說一下線程池,我們可以先講一下線程池的核心思想:
1.復(fù)用線程,降低線程創(chuàng)建與銷毀代價(jià)。
2.提升處理速度,避免了等待線程創(chuàng)建的時(shí)間。
3.池化,方便統(tǒng)一管理與監(jiān)控。
總體實(shí)現(xiàn)
ThreadPoolExecutor是線程池的核心類,主要負(fù)責(zé)線程管理和任務(wù)分發(fā)

線程池本身就是一個(gè)生產(chǎn)-消費(fèi)者模型,將任務(wù)生產(chǎn)與任務(wù)消費(fèi)完全解耦,達(dá)到緩沖目的。
任務(wù)管理
當(dāng)用戶提交一個(gè)任務(wù)后,接下來這個(gè)任務(wù)將如何執(zhí)行:
1.直接拿到核心線程進(jìn)行任務(wù)執(zhí)行
2.進(jìn)入到緩沖隊(duì)列,等待非核心線程
3.拒絕
源碼如下:
public void execute(Runnable command) {
if (command == null)
throw new NullPointerException();
int c = ctl.get();
//直接拿到核心線程進(jìn)行任務(wù)執(zhí)行
if (workerCountOf(c) < corePoolSize) {
if (addWorker(command, true))
return;
c = ctl.get();
}
//進(jìn)入到緩沖隊(duì)列,等待非核心線程
if (isRunning(c) && workQueue.offer(command)) {
int recheck = ctl.get();
if (! isRunning(recheck) && remove(command))
reject(command);
else if (workerCountOf(recheck) == 0)
addWorker(null, false);
}
//拒絕
else if (!addWorker(command, false))
reject(command);
}
源碼邏輯:
1.如果workerCount < corePoolSize 則啟動(dòng)新線程
2.如果workerCount >= corePoolSize 則加入緩沖隊(duì)列,等待執(zhí)行
3.如果 workerCount < maximumPoolSize ,并且緩沖隊(duì)列已滿,則啟動(dòng)新線程
4.workerCount > maximumPoolSize 執(zhí)行拒絕策略
任務(wù)緩沖
線程池本身是個(gè)生產(chǎn)消費(fèi)者模式,用戶將任務(wù)生產(chǎn)到任務(wù)隊(duì)列,然后線程從任務(wù)隊(duì)列拿任務(wù)。線程池的隊(duì)列是BlockingQueue,但是線程池可以通過不同的Queue實(shí)現(xiàn)不一樣的存儲(chǔ)策略。
ArrayBlockingQueue:規(guī)定大小的阻塞隊(duì)列,元素先進(jìn)先出,要指定容量。
LinkedBlockingQueue:默認(rèn)大小為Integer.MAX_VALUE,要注意容量。
PriorityBlockingQueue:自定義實(shí)現(xiàn)compareTo()方法來置頂元素排序規(guī)則,不能保證同優(yōu)先級(jí)元素的順序。
SynchronousQueue:每一個(gè)put操作必須等待take操作,否則不能添加元素,如果有空閑線程則會(huì)重復(fù)使用,線程空閑了60s后會(huì)被自動(dòng)回收。
任務(wù)拒絕
線程池有一個(gè)最大的容量,當(dāng)線程池的任務(wù)緩存隊(duì)列已滿,并且線程池中的線程數(shù)目達(dá)到maximumPoolSize時(shí),就需要拒絕掉該任務(wù),采取任務(wù)拒絕策略,保護(hù)線程池。
下篇會(huì)講一下線程池中的worker是如何執(zhí)行任務(wù)的,線程是如何復(fù)用的。