日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪(fǎng)問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) >

ThreadPoolExecutor(六)——线程池关闭之后

發(fā)布時(shí)間:2024/3/13 59 豆豆
生活随笔 收集整理的這篇文章主要介紹了 ThreadPoolExecutor(六)——线程池关闭之后 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

?上一篇主要從代碼角度介紹了線(xiàn)程池關(guān)閉相關(guān)的方法,包括各個(gè)方法之間的邏輯關(guān)系,調(diào)用關(guān)系和產(chǎn)生的效果。

這一篇更多從邏輯角度上來(lái)說(shuō)一下線(xiàn)程池在shutdown之后,原來(lái)正常的處理流程有哪些變化,既是總結(jié)也是擴(kuò)展。

shutdown操作之后,首先最重要的一點(diǎn)變化就是線(xiàn)程池狀態(tài)變成了SHUTDOWN。該狀態(tài)是開(kāi)始關(guān)閉線(xiàn)程池之后,從RUNNING改變狀態(tài)經(jīng)過(guò)的第一個(gè)狀態(tài)(還有一種情況是直接進(jìn)STOP,調(diào)用shutdownNow的時(shí)候),有個(gè)圖畫(huà)的挺好,見(jiàn)博客Java 7之多線(xiàn)程線(xiàn)程池 - 線(xiàn)程池原理(2)

從入口開(kāi)始看,在這個(gè)狀態(tài)變化之后,每個(gè)方法的處理流程和之前比發(fā)生了什么變化?

1.execute

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);}

有以下幾種情況:

1.如果現(xiàn)在狀態(tài)不是RUNNING,說(shuō)明要么正在SHUTDOWN要么已經(jīng)SHUTDOWN完畢了,這時(shí)isRunning方法是false,會(huì)走到最后一個(gè)else if中,通過(guò)addWorker的狀態(tài)來(lái)執(zhí)行相應(yīng)操作。addWorker下一個(gè)段落會(huì)說(shuō)。

2.如果現(xiàn)在是RUNNING操作,而且入隊(duì)列成功了,然后這里需要一個(gè)double check,重新檢測(cè)線(xiàn)程池的狀態(tài),如果不是RUNNING,而且remove成功,直接reject任務(wù)。如果remove方法失敗,什么都不做(因?yàn)橛衅渌姆椒ㄕ趓emove任務(wù),比如shoutDownNow的drainQueue,purge,runWorker結(jié)束時(shí)的processWorkerExit)。

3.如果現(xiàn)在是RUNNING操作,如果offer失敗了,說(shuō)明隊(duì)列滿(mǎn)了,也執(zhí)行最后一個(gè)if else,調(diào)用addWorker,這時(shí)也可能開(kāi)啟了SHUTDOWN操作。

2.addWorker

// Check if queue empty only if necessary.if (rs >= SHUTDOWN &&! (rs == SHUTDOWN &&firstTask == null &&! workQueue.isEmpty()))return false;

先看這個(gè)會(huì)返回false的判斷,

1.STOP,TIDYING和TERMINATED這三種狀態(tài)都會(huì)直接返回false。

2.如果是SHUTDOWN,而且firstTask不是null,也返回false。

3.如果是SHUTDOWN,firstTask是null,而且任務(wù)隊(duì)列是空,返回false。

現(xiàn)在要看的是SHUTDOWN狀態(tài),fistTask是null,任務(wù)隊(duì)列不是空的情況。

addWorker(null, X)這種傳參方式,除了初始化線(xiàn)程數(shù)的時(shí)候,只有processWorkerExit,execute的recheck發(fā)現(xiàn)wc個(gè)數(shù)為0,這兩種情況。

關(guān)于addWorker傳null的含義還有些迷惑,上一篇中也特意有一個(gè)段落說(shuō)這個(gè)問(wèn)題,以后再研究下看看有沒(méi)有新的理解和發(fā)現(xiàn)。

3.getTask

/*** Performs blocking or timed wait for a task, depending on* current configuration settings, or returns null if this worker* must exit because of any of:* 1. There are more than maximumPoolSize workers (due to* a call to setMaximumPoolSize).* 2. The pool is stopped.* 3. The pool is shutdown and the queue is empty.* 4. This worker timed out waiting for a task, and timed-out* workers are subject to termination (that is,* {@code allowCoreThreadTimeOut || workerCount > corePoolSize})* both before and after the timed wait.** @return task, or null if the worker must exit, in which case* workerCount is decremented*/private Runnable getTask() {boolean timedOut = false; // Did the last poll() time out?retry: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;}boolean timed; // Are workers subject to culling?for (;;) {int wc = workerCountOf(c);timed = allowCoreThreadTimeOut || wc > corePoolSize;if (wc <= maximumPoolSize && ! (timedOut && timed))break;if (compareAndDecrementWorkerCount(c))return null;c = ctl.get(); // Re-read ctlif (runStateOf(c) != rs)continue retry;// else CAS failed due to workerCount change; retry inner loop}try {Runnable r = timed ?workQueue.poll(keepAliveTime, TimeUnit.NANOSECONDS) :workQueue.take();if (r != null)return r;timedOut = true;} catch (InterruptedException retry) {timedOut = false;}}}

先看注釋:

在取任務(wù)的時(shí)候有兩種策略,一直阻塞或帶超時(shí)的等待,取決于線(xiàn)程池的參數(shù)設(shè)置。返回null如果該Worker由于以下幾種情況退出:

1.wc的數(shù)量超過(guò)了maximumPoolSize了(通常由于)調(diào)用了setMaximumPoolSize方法臨時(shí)減小了maximumPoolSize值,這時(shí)返回null來(lái)干掉Worker。

2.線(xiàn)程池處于STOP狀態(tài)。

3.線(xiàn)程池處于SHUTDOWN狀態(tài),而且任務(wù)隊(duì)列是空的。

4.Worker在等待任務(wù)的時(shí)候超時(shí)了,而且超時(shí)的Worker需要被terminated,條件是allowCoreThreadTimeOut || workerCount > corePoolSize,即當(dāng)該線(xiàn)程池允許核心線(xiàn)程timeout(無(wú)論是max還是core的Worker都會(huì)退出)或者當(dāng)前wc個(gè)數(shù)已經(jīng)超過(guò)了核心線(xiàn)程數(shù)的時(shí)候(退出的max線(xiàn)程的Worker),Worker可以退出線(xiàn)程池。
?

4.runWorker

runWorker中調(diào)用了getTask方法,所以其相應(yīng)執(zhí)行結(jié)果和getTask的返回有關(guān)。比如上一個(gè)段落中說(shuō)的那幾種情況,線(xiàn)程池在SHUTDOWN狀態(tài)且任務(wù)隊(duì)列為空,會(huì)返回null。線(xiàn)程池在STOP狀態(tài)也會(huì)返回null(不檢查隊(duì)列是否為空,因?yàn)镾TOP狀態(tài)是shutdownNow引起的,所有task都已經(jīng)被drainQueue方法移除了)。

而返回null意味著runWorker中的循環(huán)會(huì)結(jié)束,然后調(diào)用processWorkerExit方法去做一些Worker退出的相關(guān)操作。

總結(jié)

以上是生活随笔為你收集整理的ThreadPoolExecutor(六)——线程池关闭之后的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。