摘要:接上文線程池的原理學(xué)習(xí)二深入剖析線程池的五種狀態(tài)類(lèi)中將線程狀態(tài)分為了以下五種可以接受新任務(wù)并且處理進(jìn)入隊(duì)列中的任務(wù)不接受新任務(wù),但是仍然執(zhí)行隊(duì)列中的任務(wù)不接受新任務(wù)也不執(zhí)行隊(duì)列中的任務(wù)所有任務(wù)中止,隊(duì)列為空,進(jìn)入該狀態(tài)下的任務(wù)會(huì)執(zhí)行方法方法
接上文:java線程池的原理學(xué)習(xí)(二)
ThreadPoolExecutor深入剖析 線程池的五種狀態(tài)ThreadPoolExecutor 類(lèi)中將線程狀態(tài)( runState)分為了以下五種:
狀態(tài)之間的轉(zhuǎn)換RUNNING:可以接受新任務(wù)并且處理進(jìn)入隊(duì)列中的任務(wù)
SHUTDOWN:不接受新任務(wù),但是仍然執(zhí)行隊(duì)列中的任務(wù)
STOP:不接受新任務(wù)也不執(zhí)行隊(duì)列中的任務(wù)
TIDYING:所有任務(wù)中止,隊(duì)列為空,進(jìn)入該狀態(tài)下的任務(wù)會(huì)執(zhí)行 terminated()方法
TERMINATED: terminated()方法執(zhí)行完成后進(jìn)入該狀態(tài)
RUNNING -> SHUTDOWN
調(diào)用了 shutdown()方法,可能是在 finalize()方法中被隱式調(diào)用
(RUNNING or SHUTDOWN) -> STOP
調(diào)用 shutdownNow()
SHUTDOWN -> TIDYING
當(dāng)隊(duì)列和線程池都為空時(shí)
STOP -> TIDYING
線程池為空時(shí)
TIDYING -> TERMINATED
terminated()方法執(zhí)行完成
線程池狀態(tài)實(shí)現(xiàn)如果查看 ThreadPoolExecutor的源碼,會(huì)發(fā)現(xiàn)開(kāi)頭定義了這幾個(gè)變量來(lái)代表線程狀態(tài)和活動(dòng)線程的數(shù)量:
//原子變量 private final AtomicInteger ctl = new AtomicInteger(ctlOf(RUNNING, 0)); private static final int COUNT_BITS = Integer.SIZE - 3; private static final int CAPACITY = (1 << COUNT_BITS) - 1; // runState is stored in the high-order bits private static final int RUNNING = -1 << COUNT_BITS; private static final int SHUTDOWN = 0 << COUNT_BITS; private static final int STOP = 1 << COUNT_BITS; private static final int TIDYING = 2 << COUNT_BITS; private static final int TERMINATED = 3 << COUNT_BITS;
這個(gè)類(lèi)中將二進(jìn)制數(shù)分為了兩部分,高位代表線程池狀態(tài)( runState),低位代表活動(dòng)線程數(shù)( workerCount), CAPACITY代表最大的活動(dòng)線程數(shù),為2^29-1,下面為了更直觀的看到這些數(shù)我做了些打?。?/p>
public class Test1 { public static void main(String[] args) { final int COUNT_BITS = Integer.SIZE - 3; final int CAPACITY = (1 << COUNT_BITS) - 1; final int RUNNING = -1 << COUNT_BITS; final int SHUTDOWN = 0 << COUNT_BITS; final int STOP = 1 << COUNT_BITS; final int TIDYING = 2 << COUNT_BITS; final int TERMINATED = 3 << COUNT_BITS; System.out.println(Integer.toBinaryString(CAPACITY)); System.out.println(Integer.toBinaryString(RUNNING)); System.out.println(Integer.toBinaryString(SHUTDOWN)); System.out.println(Integer.toBinaryString(STOP)); System.out.println(Integer.toBinaryString(TIDYING)); System.out.println(Integer.toBinaryString(TERMINATED)); } }
輸出:
11111111111111111111111111111 11100000000000000000000000000000 0 100000000000000000000000000000 1000000000000000000000000000000 1100000000000000000000000000000
打印的時(shí)候會(huì)將高位0省略
可以看到,第一行代表線程容量,后面5行提取高3位得到:
111 - RUNNING 000 - SHUTDOWN 001 - STOP 010 - TIDYING 011 - TERMINATED
分別對(duì)應(yīng)5種狀態(tài),可以看到這樣定義之后,只需要通過(guò)簡(jiǎn)單的移位操作就可以進(jìn)行狀態(tài)的轉(zhuǎn)換。
重要方法execute方法:
public void execute(Runnable command) { if (command == null) throw new NullPointerException(); int c = ctl.get(); /**分三步執(zhí)行 * 如果workerCount=corePoolSize,判斷線程池是否處于運(yùn)行狀態(tài),再將任務(wù)加入隊(duì)列 * */ if (isRunning(c) && workQueue.offer(command)) { int recheck = ctl.get(); //用于double check //如果線程池處于非運(yùn)行態(tài),則將任務(wù)從緩存隊(duì)列中刪除 if (! isRunning(recheck) && remove(command)) reject(command); //拒絕任務(wù) else if (workerCountOf(recheck) == 0) //如果活動(dòng)線程數(shù)為0,則創(chuàng)建新線程 addWorker(null, false); } //如果線程池不處于RUNNING狀態(tài),或者workQueue滿了,則執(zhí)行以下代碼 else if (!addWorker(command, false)) reject(command); }
可以看到,在類(lèi)中使用了 Work類(lèi)來(lái)代表任務(wù),下面是 Work類(lèi)的簡(jiǎn)單摘要:
private final class Worker extends AbstractQueuedSynchronizer implements Runnable { /** Thread this worker is running in. Null if factory fails. */ final Thread thread; /** Initial task to run. Possibly null. */ Runnable firstTask; /** Per-thread task counter */ volatile long completedTasks; /** * Creates with given first task and thread from ThreadFactory. * @param firstTask the first task (null if none) */ Worker(Runnable firstTask) { this.firstTask = firstTask; this.thread = getThreadFactory().newThread(this); } /** Delegates main run loop to outer runWorker */ public void run() { runWorker(this); } ...
Work類(lèi)實(shí)現(xiàn)了 Runnable接口,使用了線程工廠創(chuàng)建線程,使用 runWork方法來(lái)運(yùn)行任務(wù)
創(chuàng)建新線程時(shí)用到了 addWorker()方法:
/** * 檢查在當(dāng)前線程池狀態(tài)和限制下能否創(chuàng)建一個(gè)新線程,如果可以,會(huì)相應(yīng)改變workerCount, * 每個(gè)worker都會(huì)運(yùn)行他們的firstTask * @param firstTask 第一個(gè)任務(wù) * @param core true使用corePoolSize作為邊界,false使用maximumPoolSize * @return false 線程池關(guān)閉或者已經(jīng)具備關(guān)閉的條件或者線程工廠沒(méi)有創(chuàng)建新線程 */
private boolean addWorker(Runnable firstTask, boolean core) { retry: for (;;) { int c = ctl.get(); int rs = runStateOf(c); // 只有當(dāng)rs < SHUTDOWN才有可能接受新任務(wù) if (rs >= SHUTDOWN && ! (rs == SHUTDOWN && firstTask == null && ! workQueue.isEmpty())) return false; for (;;) { int wc = workerCountOf(c); //工作線程數(shù)量 if (wc >= CAPACITY || wc >= (core ? corePoolSize : maximumPoolSize)) //不合法則返回 return false; if (compareAndIncrementWorkerCount(c)) //將工作線程數(shù)量+1 break retry; c = ctl.get(); // Re-read ctl if (runStateOf(c) != rs) //判斷線程池狀態(tài)有沒(méi)有改變,改變了則進(jìn)行外循環(huán),否則只進(jìn)行內(nèi)循環(huán) continue retry; // else CAS failed due to workerCount change; retry inner loop } } //創(chuàng)建新線程 Worker w = new Worker(firstTask); Thread t = w.thread; final ReentrantLock mainLock = this.mainLock; mainLock.lock(); try { //再次檢查狀態(tài),防止ThreadFactory創(chuàng)建線程失敗或者狀態(tài)改變了 int c = ctl.get(); int rs = runStateOf(c); if (t == null || (rs >= SHUTDOWN && ! (rs == SHUTDOWN && firstTask == null))) { decrementWorkerCount(); //減少線程數(shù)量 tryTerminate();//嘗試中止線程 return false; } workers.add(w);//添加到工作線程Set集合中 int s = workers.size(); if (s > largestPoolSize) largestPoolSize = s; } finally { mainLock.unlock(); } t.start();//執(zhí)行任務(wù) //狀態(tài)變成了STOP(調(diào)用了shutdownNow方法) if (runStateOf(ctl.get()) == STOP && ! t.isInterrupted()) t.interrupt(); return true; }
再看 Work中的 runWork方法:
final void runWorker(Worker w) { Runnable task = w.firstTask; w.firstTask = null; boolean completedAbruptly = true;//線程是否異常中止 try { //先取firstTask,再?gòu)年?duì)列中取任務(wù)直到為null while (task != null || (task = getTask()) != null) { w.lock(); clearInterruptsForTaskRun(); try { beforeExecute(w.thread, task);//實(shí)現(xiàn)鉤子方法 Throwable thrown = null; try { task.run();//運(yùn)行任務(wù) } 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);//實(shí)現(xiàn)鉤子方法 } } finally { task = null; w.completedTasks++; w.unlock(); } } completedAbruptly = false;//成功運(yùn)行,說(shuō)明沒(méi)有異常中止 } finally { processWorkerExit(w, completedAbruptly); } }
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://specialneedsforspecialkids.com/yun/64431.html
摘要:當(dāng)活動(dòng)線程核心線程非核心線程達(dá)到這個(gè)數(shù)值后,后續(xù)任務(wù)將會(huì)根據(jù)來(lái)進(jìn)行拒絕策略處理。線程池工作原則當(dāng)線程池中線程數(shù)量小于則創(chuàng)建線程,并處理請(qǐng)求。當(dāng)線程池中的數(shù)量等于最大線程數(shù)時(shí)默默丟棄不能執(zhí)行的新加任務(wù),不報(bào)任何異常。 spring-cache使用記錄 spring-cache的使用記錄,坑點(diǎn)記錄以及采用的解決方案 深入分析 java 線程池的實(shí)現(xiàn)原理 在這篇文章中,作者有條不紊的將 ja...
摘要:你僅僅需要一個(gè)大小為數(shù)據(jù)庫(kù)連接池,然后讓剩下的業(yè)務(wù)線程都在隊(duì)列里等待就可以了。你應(yīng)該經(jīng)常會(huì)看到一些用戶(hù)量不是很大的應(yīng)用中,為應(yīng)付大約十來(lái)個(gè)的并發(fā),卻將數(shù)據(jù)庫(kù)連接池設(shè)置成,的情況。請(qǐng)不要過(guò)度配置您的數(shù)據(jù)庫(kù)連接池的大小。 文章翻譯整理自: https://github.com/brettwooldridge/HikariCP/wiki/About-Pool-Sizing歡迎關(guān)注個(gè)人微信公眾...
摘要:你僅僅需要一個(gè)大小為數(shù)據(jù)庫(kù)連接池,然后讓剩下的業(yè)務(wù)線程都在隊(duì)列里等待就可以了。你應(yīng)該經(jīng)常會(huì)看到一些用戶(hù)量不是很大的應(yīng)用中,為應(yīng)付大約十來(lái)個(gè)的并發(fā),卻將數(shù)據(jù)庫(kù)連接池設(shè)置成,的情況。請(qǐng)不要過(guò)度配置您的數(shù)據(jù)庫(kù)連接池的大小。 文章翻譯整理自: https://github.com/brettwooldridge/HikariCP/wiki/About-Pool-Sizing歡迎關(guān)注個(gè)人微信公眾...
摘要:接上文線程池的原理學(xué)習(xí)簡(jiǎn)單介紹,線程池類(lèi),繼承自構(gòu)造方法提供了四種構(gòu)造方法實(shí)現(xiàn)這里只介紹一種有必要對(duì)每個(gè)參數(shù)解釋一下池中所保存的線程數(shù),包括空閑線程。文檔中提供了一個(gè)可以暫停和恢復(fù)的線程池例子運(yùn)行原理線程池的原理學(xué)習(xí)三 接上文:java線程池的原理學(xué)習(xí) ThreadPoolExecutor簡(jiǎn)單介紹 ThreadPoolExecutor,線程池類(lèi),繼承自 AbstractExecutor...
閱讀 3517·2021-09-27 13:35
閱讀 3557·2019-08-29 17:09
閱讀 2426·2019-08-26 11:30
閱讀 697·2019-08-26 10:32
閱讀 532·2019-08-26 10:23
閱讀 1193·2019-08-26 10:20
閱讀 3150·2019-08-23 15:26
閱讀 3551·2019-08-23 14:33