java線程池中線程數(shù)量到底是幾
線程池配置
線程池配置,假設(shè)是:
1.最小數(shù)量是5
2.阻塞隊(duì)列容量是10
3.最大數(shù)量是20
線程池里的業(yè)務(wù)線程數(shù)量小于最小數(shù)量(5)
第一個(gè)請(qǐng)求
第一個(gè)請(qǐng)求進(jìn)來(lái)的時(shí)候,這個(gè)時(shí)候,線程池沒(méi)有線程,就創(chuàng)建新的工作線程(即Worker線程)。
然后,這個(gè)工作線程去處理當(dāng)前請(qǐng)求的業(yè)務(wù)線程。
第二個(gè)請(qǐng)求
第二個(gè)請(qǐng)求進(jìn)來(lái)的時(shí)候,這個(gè)時(shí)候,線程池已經(jīng)有了一個(gè)工作線程。
但是,要注意,這個(gè)時(shí)候是不會(huì)復(fù)用線程池里已有的工作線程的。而是創(chuàng)建新的工作線程。
因?yàn)?,線程池里根本沒(méi)有復(fù)用線程的概念。
說(shuō)白了,無(wú)論線程池里已有的這個(gè)工作線程是否在處理業(yè)務(wù)線程,即不管它空閑與否,其實(shí)都會(huì)創(chuàng)建新的工作線程。
第三個(gè)請(qǐng)求
同上,仍然創(chuàng)建新的工作線程。
。。。
第五個(gè)請(qǐng)求
同上。仍然創(chuàng)建新的工作線程。
注意,現(xiàn)在,線程池有幾個(gè)工作線程?5個(gè)。
即,每個(gè)請(qǐng)求進(jìn)來(lái),都創(chuàng)建一個(gè)新的工作線程。
小于阻塞隊(duì)列容量(10)
第六個(gè)請(qǐng)求
第六個(gè)請(qǐng)求進(jìn)來(lái)的時(shí)候,提交到阻塞隊(duì)列。
然后,再慢慢消費(fèi)。
具體來(lái)說(shuō),是由線程池里的工作線程來(lái)慢慢消費(fèi)。
具體消費(fèi)的源碼,參考:復(fù)用線程小節(jié)。
第七個(gè)請(qǐng)求
同上,也是先添加到阻塞隊(duì)列。
。。。
第15個(gè)請(qǐng)求
同上,也是先添加到阻塞隊(duì)列。
小于最大數(shù)量(20)
第16個(gè)請(qǐng)求
先來(lái)看,正常情況下,阻塞隊(duì)列還沒(méi)塞滿(生產(chǎn)環(huán)境的容量一般是1000),就會(huì)被快速處理掉。
然后,當(dāng)新的請(qǐng)求進(jìn)來(lái)的時(shí)候,繼續(xù)丟到阻塞隊(duì)列里面去。
這個(gè)是和上面講的一樣。
但是,我們?yōu)榱朔奖憷斫猓F(xiàn)在假設(shè)之前的15個(gè)請(qǐng)求是同時(shí)到達(dá),即
- 前面5個(gè)請(qǐng)求
創(chuàng)建5個(gè)新的請(qǐng)求。
- 后面10個(gè)請(qǐng)求
全部丟到阻塞隊(duì)列。
這個(gè)時(shí)候,阻塞隊(duì)列已經(jīng)滿了。接著,第16個(gè)請(qǐng)求進(jìn)來(lái)了,怎么辦?
繼續(xù)創(chuàng)建新的工作線程。
。。。
第35個(gè)請(qǐng)求
同上,繼續(xù)創(chuàng)建新的工作線程。
注意,這個(gè)時(shí)候,線程池里的工作線程的數(shù)量是多少?20。
因?yàn)?/p>
- 前面5個(gè)請(qǐng)求,創(chuàng)建了5個(gè)新的工作線程。
- 最后面的15個(gè)請(qǐng)求(第16到第35),創(chuàng)建了15個(gè)新的工作線程。
所以,總共,創(chuàng)建了20個(gè)新的工作線程。線程池,總共有20個(gè)工作線程。
拒絕策略
第36個(gè)請(qǐng)求
假設(shè)前面的請(qǐng)求都沒(méi)有處理完,這個(gè)時(shí)候,來(lái)了第36個(gè)請(qǐng)求,怎么辦?
只能采取拒絕策略。
具體采用哪個(gè)拒絕策略?比如說(shuō),一般情況下,都是采用丟棄。
復(fù)用線程
前面說(shuō)了,線程池里沒(méi)有復(fù)用線程的概念。
那到底是怎么回事呢?既然不能復(fù)用線程,那搞個(gè)線程池有個(gè)幾把用?
具體是這樣子,雖然,線程池里的工作線程不能被復(fù)用,僅僅是指類似數(shù)據(jù)庫(kù)連接池里的連接的那種復(fù)用,即
- 用的時(shí)候,從連接池取
- 用完了,歸還到連接池
線程池里的對(duì)象復(fù)用,是基于循環(huán),而不是用完之后再還回去。
什么意思呢?就是工作線程,不斷的從阻塞隊(duì)列里取業(yè)務(wù)線程,然后執(zhí)行業(yè)務(wù)線程。
偽代碼
工作線程{
run(){
while(){
1.從阻塞隊(duì)列,取業(yè)務(wù)線程
2.執(zhí)行業(yè)務(wù)線程;
}
}
}所以,線程池和連接池的區(qū)別在于,線程池的對(duì)象是線程,可以不斷的循環(huán)讀業(yè)務(wù)線程。而連接池的對(duì)象,是用完了歸還到連接池里去。
jdk源碼-java.util.concurrent.ThreadPoolExecutor#runWorker
/**
* 核心步驟
* 1.從阻塞隊(duì)列,讀業(yè)務(wù)線程
* 2.執(zhí)行業(yè)務(wù)線程
*
* ---
* Main worker run loop. Repeatedly gets tasks from queue and
* executes them, while coping with a number of issues:
*
* 1. We may start out with an initial task, in which case we
* don't need to get the first one. Otherwise, as long as pool is
* running, we get tasks from getTask. If it returns null then the
* worker exits due to changed pool state or configuration
* parameters. Other exits result from exception throws in
* external code, in which case completedAbruptly holds, which
* usually leads processWorkerExit to replace this thread.
*
* 2. Before running any task, the lock is acquired to prevent
* other pool interrupts while the task is executing, and then we
* ensure that unless pool is stopping, this thread does not have
* its interrupt set.
*
* 3. Each task run is preceded by a call to beforeExecute, which
* might throw an exception, in which case we cause thread to die
* (breaking loop with completedAbruptly true) without processing
* the task.
*
* 4. Assuming beforeExecute completes normally, we run the task,
* gathering any of its thrown exceptions to send to afterExecute.
* We separately handle RuntimeException, Error (both of which the
* specs guarantee that we trap) and arbitrary Throwables.
* Because we cannot rethrow Throwables within Runnable.run, we
* wrap them within Errors on the way out (to the thread's
* UncaughtExceptionHandler). Any thrown exception also
* conservatively causes thread to die.
*
* 5. After task.run completes, we call afterExecute, which may
* also throw an exception, which will also cause thread to
* die. According to JLS Sec 14.20, this exception is the one that
* will be in effect even if task.run throws.
*
* The net effect of the exception mechanics is that afterExecute
* and the thread's UncaughtExceptionHandler have as accurate
* information as we can provide about any problems encountered by
* user code.
*
* @param w the worker
*/
final void runWorker(Worker w) {
Thread wt = Thread.currentThread();
Runnable task = w.firstTask;
w.firstTask = null;
w.unlock(); // allow interrupts
boolean completedAbruptly = true;
try {
//從阻塞隊(duì)列里獲取業(yè)務(wù)線程
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 {
//執(zhí)行業(yè)務(wù)線程
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);
}
}到此這篇關(guān)于java線程池中線程數(shù)量到底是幾的文章就介紹到這了,更多相關(guān)java 線程數(shù)量?jī)?nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
springcloud整合gateway實(shí)現(xiàn)網(wǎng)關(guān)全局過(guò)濾器功能
本文主要介紹了springcloud整合gateway實(shí)現(xiàn)網(wǎng)關(guān)全局過(guò)濾器功能,文中通過(guò)示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-02-02
Java對(duì)時(shí)間的簡(jiǎn)單操作實(shí)例
這篇文章主要介紹了Java對(duì)時(shí)間的簡(jiǎn)單操作,實(shí)例分析了針對(duì)java.util.Date的各類常見(jiàn)操作,具有一定參考借鑒價(jià)值,需要的朋友可以參考下2015-01-01
java獲取ip地址與網(wǎng)絡(luò)接口的方法示例
這篇文章主要給大家介紹了關(guān)于利用java如何獲取ip地址與網(wǎng)絡(luò)接口的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧。2018-01-01
SpringBoot+Dubbo+Zookeeper實(shí)現(xiàn)簡(jiǎn)單分布式開(kāi)發(fā)的應(yīng)用詳解
這篇文章主要介紹了SpringBoot+Dubbo+Zookeeper實(shí)現(xiàn)簡(jiǎn)單分布式開(kāi)發(fā)的應(yīng)用詳解,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2021-01-01
spring boot輸入數(shù)據(jù)校驗(yàn)(validation)的實(shí)現(xiàn)過(guò)程
web項(xiàng)目中,用戶的輸入總是被假定不安全不正確的,在被處理前需要做校驗(yàn)。本文介紹在spring boot項(xiàng)目中實(shí)現(xiàn)數(shù)據(jù)校驗(yàn)的過(guò)程,通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),需要的朋友參考下吧2021-09-09
鑒權(quán)認(rèn)證+aop+注解+過(guò)濾feign請(qǐng)求的實(shí)例
這篇文章主要介紹了鑒權(quán)認(rèn)證+aop+注解+過(guò)濾feign請(qǐng)求的實(shí)例講解,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-03-03

