Java提供的線程池出自并發(fā)大師Doug Lea之手角骤,向大師致敬讥邻!
1. 為什么要用線程池
合理使用線程池可以帶來(lái)3個(gè)好處:
- 降低資源消耗夷野。重復(fù)利用已經(jīng)創(chuàng)建的線程蒿辙,避免線程重復(fù)創(chuàng)建帶來(lái)的消耗拇泛。
- 提高響應(yīng)速度。當(dāng)任務(wù)到達(dá)時(shí)思灌,任務(wù)不必等線程創(chuàng)建即可立即執(zhí)行俺叭。
-
提高線程的可管理性。使用線程池可以對(duì)線程統(tǒng)一分配泰偿、調(diào)優(yōu)和監(jiān)控熄守。
總之,線程池是為了資源復(fù)用耗跛、提高效率裕照、方便管理的產(chǎn)物〉魉“池”的作用有兩點(diǎn):一是復(fù)用已有資源晋南,二是控制資源總量
2. 線程池的原理
當(dāng)向線程池提交了一個(gè)任務(wù)之后,線程池是如何處理這個(gè)任務(wù)的呢羔砾?
- 首先線程池判斷核心線程池的線程是否都在執(zhí)行任務(wù)搬俊,如果不是澤創(chuàng)建一個(gè)線程執(zhí)行任務(wù),否則就如下一個(gè)流程蜒茄。
- 線程池判斷任務(wù)隊(duì)列是否已經(jīng)滿了唉擂,如果沒(méi)有滿則將任務(wù)存儲(chǔ)在工作隊(duì)列里面,如果滿了則進(jìn)入下一個(gè)流程檀葛。
-
線程池判斷線程是否都已經(jīng)處于工作狀態(tài)玩祟,如果沒(méi)有則創(chuàng)建一個(gè)線程執(zhí)行任務(wù),如果已經(jīng)滿了則交給策略處理無(wú)法完成的任務(wù)屿聋。
線程池任務(wù)處理流程
ThreadPoolExecutor執(zhí)行示意圖
3. 線程池的使用
通過(guò)ThreadPoolExecutor來(lái)創(chuàng)建一個(gè)線程池:
new ThreadPoolExecutor(corePoolSize, maxPoolSize, keepAliveTime, unit, queue)
創(chuàng)建完成后通過(guò)ThreadPoolExecutor的execute(sumbmit最終也是調(diào)用execute執(zhí)行任務(wù))方法向線程池提交任務(wù)空扎,代碼如下:
public void execute(Runnable command) {
if (command == null)
throw new NullPointerException();
int c = ctl.get();
if (workerCountOf(c) < corePoolSize) {
if (addWorker(command, true))
return;
c = ctl.get();
}
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);
}
- execute方法首先判斷當(dāng)前運(yùn)行線程少于corePoolSize藏鹊,則創(chuàng)建新線程任務(wù)來(lái)執(zhí)行任務(wù)
- 如果運(yùn)行線程等于或多于corePoolSize,則將任務(wù)加入到隊(duì)列
- 如果無(wú)法將任務(wù)加入到隊(duì)列转锈,則創(chuàng)建新線程執(zhí)行任務(wù)
- 創(chuàng)建新線程時(shí)如果數(shù)量超過(guò)maxPoolSize則拒絕執(zhí)行任務(wù)盘寡,這里需要注意一下如果構(gòu)造ThreadPoolExecutor傳入的是無(wú)界隊(duì)列,maxPoolSize無(wú)效撮慨,最大線程數(shù)將是corePoolSize