java線程池核心線程不被摧毀的原理及分析
為什么要用線程池?
- 減少了創(chuàng)建和銷毀線程的次數(shù),每個(gè)工作線程都可以被重復(fù)利用
- 可以根據(jù)系統(tǒng)的承受能力,調(diào)整線程池中工作線線程的數(shù)目,防止因線程過(guò)多消耗內(nèi)存,也避免了因線程過(guò)少,浪費(fèi)系統(tǒng)資源
如何做到每個(gè)工作線程都可以被重復(fù)利用呢?
先看下線程池的工作原理:

原理如上圖,線程池有七個(gè)核心參數(shù)
corePoolSize線程池核心線程數(shù)maximumPoolSize線程池最大線程數(shù)量keepAliveTime空閑線程存活時(shí)間unit空閑線程存活時(shí)間單位workQueue工作隊(duì)列threadFactory線程工廠handler拒絕策略
線程池之所以能做到重復(fù)利用,是因?yàn)榫€程池的核心線程不會(huì)被摧毀,執(zhí)行完任務(wù)后會(huì)重復(fù)利用
線程池是如何保持核心線程不被摧毀呢?
首先看先線程池是如何處理任務(wù)的,如下圖

下面我們看下核心部分源碼:
- 當(dāng)有一個(gè)任務(wù)添加進(jìn)來(lái)時(shí),線程池會(huì)創(chuàng)建一個(gè)Worker,Worker是實(shí)現(xiàn)Runnable方法的,所以Worker執(zhí)行時(shí)會(huì)調(diào)用run方法,run方法會(huì)接著調(diào)用runWoker方法
- 主要看這一行代碼,調(diào)用getTask方法獲取任務(wù)并且執(zhí)行 while (task != null || (task = getTask()) != null)
final void runWorker(Worker w) {
Thread wt = Thread.currentThread();
Runnable task = w.firstTask;
w.firstTask = null;
w.unlock(); // allow interrupts
boolean completedAbruptly = true;
try {
// 主要看這一行代碼,調(diào)用getTask方法獲取任務(wù)并且執(zhí)行
while (task != null || (task = getTask()) != null) {
w.lock();
// If pool is stopping, ensure thread is interrupted;
// if not, ensure thread is not interrupted. This
// requires a recheck in second case to deal with
// shutdownNow race while clearing interrupt
if ((runStateAtLeast(ctl.get(), STOP) ||
(Thread.interrupted() &&
runStateAtLeast(ctl.get(), STOP))) &&
!wt.isInterrupted())
wt.interrupt();
try {
beforeExecute(wt, task);
Throwable thrown = null;
try {
task.run();
} catch (RuntimeException x) {
thrown = x; throw x;
} catch (Error x) {
thrown = x; throw x;
} catch (Throwable x) {
thrown = x; throw new Error(x);
} finally {
afterExecute(task, thrown);
}
} finally {
task = null;
w.completedTasks++;
w.unlock();
}
}
completedAbruptly = false;
} finally {
processWorkerExit(w, completedAbruptly);
}
}- 看下getTask方法是如何實(shí)現(xiàn)的
private Runnable getTask() {
boolean timedOut = false; // Did the last poll() time out?
for (;;) {
int c = ctl.get();
int rs = runStateOf(c);
// Check if queue empty only if necessary.
if (rs >= SHUTDOWN && (rs >= STOP || workQueue.isEmpty())) {
decrementWorkerCount();
return null;
}
int wc = workerCountOf(c);
// Are workers subject to culling?
boolean timed = allowCoreThreadTimeOut || wc > corePoolSize;
if ((wc > maximumPoolSize || (timed && timedOut))
&& (wc > 1 || workQueue.isEmpty())) {
if (compareAndDecrementWorkerCount(c))
return null;
continue;
}
try {
Runnable r = timed ?
workQueue.poll(keepAliveTime, TimeUnit.NANOSECONDS) :
workQueue.take();
if (r != null)
return r;
timedOut = true;
} catch (InterruptedException retry) {
timedOut = false;
}
}
}- 主要看這幾行代碼

- getTask方法通過(guò)調(diào)用任務(wù)隊(duì)列的take方法,不斷的獲取線程

- 如果任務(wù)隊(duì)列里面數(shù)量為0,則會(huì)一直阻塞,一直等到有任務(wù)加入,從而保證了核心線程不被摧毀
總結(jié)
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
UniApp?+?SpringBoot?實(shí)現(xiàn)支付寶支付和退款功能
這篇文章主要介紹了UniApp?+?SpringBoot?實(shí)現(xiàn)支付寶支付和退款功能,基本的?SpringBoot?的腳手架,可以去IDEA?自帶的快速生成腳手架插件,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),需要的朋友參考下吧2022-06-06
SpringBoot使用Redis清除所有緩存實(shí)現(xiàn)方式
文章介紹通過(guò)遍歷刪除Redis所有key的方法,推薦使用RedisTemplate的delete方法而非StringRedisTemplate,需確保緩存操作統(tǒng)一使用同類型模板,避免類型不匹配問(wèn)題2025-08-08
Java的Tomcat和Servlet的運(yùn)行原理詳解
這篇文章主要為大家詳細(xì)介紹了Java的Tomcat和Servlet,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來(lái)幫助2022-03-03
Java實(shí)現(xiàn)AWT四大事件的詳細(xì)過(guò)程
AWT的事件處理是一種委派式事件處理方式:普通組件(事件源)將整個(gè)事件處理委托給特定的對(duì)象(事件監(jiān)聽(tīng)器);當(dāng)該事件源發(fā)生指定的事件時(shí),就通知所委托的事件監(jiān)聽(tīng)器,由事件監(jiān)聽(tīng)器來(lái)處理這個(gè)事件2022-04-04
mac下idea啟動(dòng)web項(xiàng)目報(bào)錯(cuò)java.net.SocketException:socket closed
本文主要介紹了作者在項(xiàng)目啟動(dòng)時(shí)遇到的一個(gè)問(wèn)題——無(wú)法打開(kāi)調(diào)試端口,經(jīng)過(guò)一系列排查和嘗試,最終發(fā)現(xiàn)是由于權(quán)限問(wèn)題導(dǎo)致的,作者還分享了如何修改文件權(quán)限的方法,并提醒大家不要隨意kill掉占用端口的進(jìn)程2024-12-12
淺談Java數(shù)值類型的轉(zhuǎn)換與強(qiáng)制轉(zhuǎn)換
這篇文章主要介紹了Java數(shù)值類型的轉(zhuǎn)換與強(qiáng)制轉(zhuǎn)換,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2019-04-04
springboot jdbctemplate如何實(shí)現(xiàn)多數(shù)據(jù)源
這篇文章主要介紹了springboot jdbctemplate如何實(shí)現(xiàn)多數(shù)據(jù)源問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-07-07

