Java併發包原始碼學習之執行緒池(一)ThreadPoolExecutor原始碼分析
Java中使用執行緒池技術一般都是使用Executors
這個工廠類,它提供了非常簡單方法來建立各種型別的執行緒池:
public static ExecutorService newFixedThreadPool(int nThreads) public static ExecutorService newSingleThreadExecutor() public static ExecutorService newCachedThreadPool() public static ScheduledExecutorService newScheduledThreadPool(intcorePoolSize)
核心的介面其實是Executor
,它只有一個execute
方法抽象為對任務(Runnable介面)的執行, ExecutorService
介面在Executor
的基礎上提供了對任務執行的生命週期的管理,主要是submit
和shutdown
方法, AbstractExecutorService
對ExecutorService
一些方法做了預設的實現,主要是submit和invoke方法,而真正的任務執行 的Executor介面execute
方法是由子類實現,就是ThreadPoolExecutor
,它實現了基於執行緒池的任務執行框架,所以要了解 JDK的執行緒池,那麼就得先看這個類。
再看execute
方法之前需要先介幾個變數或類。
ctl
private final AtomicInteger ctl = new AtomicInteger(ctlOf(RUNNING, 0));
這個變數是整個類的核心,AtomicInteger
保證了對這個變數的操作是原子的,通過巧妙的操作,ThreadPoolExecutor用這一個變數儲存了兩個內容:
- 所有有效執行緒的數量
- 各個執行緒的狀態(runState)
低29位存執行緒數,高3位存runState
,這樣runState有5個值:
- RUNNING:-536870912
- SHUTDOWN:0
- STOP:536870912
- TIDYING:1073741824
- TERMINATED:1610612736
執行緒池中各個狀態間的轉換比較複雜,主要記住下面內容就可以了:
- RUNNING狀態:執行緒池正常執行,可以接受新的任務並處理佇列中的任務;
- SHUTDOWN狀態:不再接受新的任務,但是會執行佇列中的任務;
- STOP狀態:不再接受新任務,不處理佇列中的任務
圍繞ctl變數有一些操作,瞭解這些方法是看懂後面一些晦澀程式碼的基礎:
/** * 這個方法用於取出runState的值 因為CAPACITY值為:00011111111111111111111111111111 * ~為按位取反操作,則~CAPACITY值為:11100000000000000000000000000000 * 再同參數做&操作,就將低29位置0了,而高3位還是保持原先的值,也就是runState的值 * * @param c * 該引數為儲存runState和workerCount的int值 * @return runState的值 */ private static int runStateOf(int c) { return c & ~CAPACITY; } /** * 這個方法用於取出workerCount的值 * 因為CAPACITY值為:00011111111111111111111111111111,所以&操作將引數的高3位置0了 * 保留引數的低29位,也就是workerCount的值 * * @param c * ctl, 儲存runState和workerCount的int值 * @return workerCount的值 */ private static int workerCountOf(int c) { return c & CAPACITY; } /** * 將runState和workerCount存到同一個int中 * “|”運算的意思是,假設rs的值是101000,wc的值是000111,則他們位或運算的值為101111 * * @param rs * runState移位過後的值,負責填充返回值的高3位 * @param wc * workerCount移位過後的值,負責填充返回值的低29位 * @return 兩者或運算過後的值 */ private static int ctlOf(int rs, int wc) { return rs | wc; } // 只有RUNNING狀態會小於0 private static boolean isRunning(int c) { return c < SHUTDOWN; }View Code
corePoolSize
核心執行緒池大小,活動執行緒小於corePoolSize則直接建立,大於等於則先加到workQueue中,佇列滿了才建立新的執行緒。
keepAliveTime
執行緒從佇列中獲取任務的超時時間,也就是說如果執行緒空閒超過這個時間就會終止。
Worker
private final class Worker extends AbstractQueuedSynchronizer implements Runnable ...
內部類Worker
是對任務的封裝,所有submit的Runnable都被封裝成了Worker,它本身也是一個Runnable, 然後利用AQS框架(關於AQS可以看我這篇文章)實現了一個簡單的非重入的互斥鎖, 實現互斥鎖主要目的是為了中斷的時候判斷執行緒是在空閒還是執行,可以看後面shutdown
和shutdownNow
方法的分析。
// state只有0和1,互斥 protected boolean tryAcquire(int unused) { if (compareAndSetState(0, 1)) { setExclusiveOwnerThread(Thread.currentThread()); return true;// 成功獲得鎖 } // 執行緒進入等待佇列 return false; } protected boolean tryRelease(int unused) { setExclusiveOwnerThread(null); setState(0); return true; }
之所以不用ReentrantLock是為了避免任務執行的程式碼中修改執行緒池的變數,如setCorePoolSize
,因為ReentrantLock是可重入的。
execute
execute
方法主要三個步驟:
- 活動執行緒小於corePoolSize的時候建立新的執行緒;
- 活動執行緒大於corePoolSize時都是先加入到任務隊列當中;
- 任務佇列滿了再去啟動新的執行緒,如果執行緒數達到最大值就拒絕任務。
public void execute(Runnable command) { if (command == null) throw new NullPointerException(); int c = ctl.get(); // 活動執行緒數 < corePoolSize if (workerCountOf(c) < corePoolSize) { // 直接啟動新的執行緒。第二個引數true:addWorker中會重新檢查workerCount是否小於corePoolSize if (addWorker(command, true)) // 新增成功返回 return; c = ctl.get(); } // 活動執行緒數 >= corePoolSize // runState為RUNNING && 佇列未滿 if (isRunning(c) && workQueue.offer(command)) { int recheck = ctl.get(); // double check // 非RUNNING狀態 則從workQueue中移除任務並拒絕 if (!isRunning(recheck) && remove(command)) reject(command);// 採用執行緒池指定的策略拒絕任務 // 執行緒池處於RUNNING狀態 || 執行緒池處於非RUNNING狀態但是任務移除失敗 else if (workerCountOf(recheck) == 0) // 這行程式碼是為了SHUTDOWN狀態下沒有活動執行緒了,但是佇列裡還有任務沒執行這種特殊情況。 // 新增一個null任務是因為SHUTDOWN狀態下,執行緒池不再接受新任務 addWorker(null, false); // 兩種情況: // 1.非RUNNING狀態拒絕新的任務 // 2.佇列滿了啟動新的執行緒失敗(workCount > maximumPoolSize) } else if (!addWorker(command, false)) reject(command); }
註釋比較清楚了就不再解釋了,其中比較難理解的應該是addWorker(null, false);
這一行,這要結合addWorker一起來看。 主要目的是防止HUTDOWN狀態下沒有活動執行緒了,但是佇列裡還有任務沒執行這種特殊情況。
addWorker
這個方法理解起來比較費勁。
private boolean addWorker(Runnable firstTask, boolean core) { retry: for (;;) { int c = ctl.get(); int rs = runStateOf(c);// 當前執行緒池狀態 // Check if queue empty only if necessary. // 這條語句等價:rs >= SHUTDOWN && (rs != SHUTDOWN || firstTask != null || // workQueue.isEmpty()) // 滿足下列調價則直接返回false,執行緒建立失敗: // rs > SHUTDOWN:STOP || TIDYING || TERMINATED 此時不再接受新的任務,且所有任務執行結束 // rs = SHUTDOWN:firtTask != null 此時不再接受任務,但是仍然會執行佇列中的任務 // rs = SHUTDOWN:firtTask == null見execute方法的addWorker(null, // false),任務為null && 佇列為空 // 最後一種情況也就是說SHUTDONW狀態下,如果佇列不為空還得接著往下執行,為什麼?add一個null任務目的到底是什麼? // 看execute方法只有workCount==0的時候firstTask才會為null結合這裡的條件就是執行緒池SHUTDOWN了不再接受新任務 // 但是此時佇列不為空,那麼還得建立執行緒把任務給執行完才行。 if (rs >= SHUTDOWN && !(rs == SHUTDOWN && firstTask == null && !workQueue.isEmpty())) return false; // 走到這的情形: // 1.執行緒池狀態為RUNNING // 2.SHUTDOWN狀態,但佇列中還有任務需要執行 for (;;) { int wc = workerCountOf(c); if (wc >= CAPACITY || wc >= (core ? corePoolSize : maximumPoolSize)) return false; if (compareAndIncrementWorkerCount(c))// 原子操作遞增workCount break retry;// 操作成功跳出的重試的迴圈 c = ctl.get(); // Re-read ctl if (runStateOf(c) != rs)// 如果執行緒池的狀態發生變化則重試 continue retry; // else CAS failed due to workerCount change; retry inner loop } } // wokerCount遞增成功 boolean workerStarted = false; boolean workerAdded = false; Worker w = null; try { final ReentrantLock mainLock = this.mainLock; w = new Worker(firstTask); final Thread t = w.thread; if (t != null) { // 併發的訪問執行緒池workers物件必須加鎖 mainLock.lock(); try { // Recheck while holding lock. // Back out on ThreadFactory failure or if // shut down before lock acquired. int c = ctl.get(); int rs = runStateOf(c); // RUNNING狀態 || SHUTDONW狀態下清理佇列中剩餘的任務 if (rs < SHUTDOWN || (rs == SHUTDOWN && firstTask == null)) { if (t.isAlive()) // precheck that t is startable throw new IllegalThreadStateException(); // 將新啟動的執行緒新增到執行緒池中 workers.add(w); // 更新largestPoolSize int s = workers.size(); if (s > largestPoolSize) largestPoolSize = s; workerAdded = true; } } finally { mainLock.unlock(); } // 啟動新新增的執行緒,這個執行緒首先執行firstTask,然後不停的從佇列中取任務執行 // 當等待keepAlieTime還沒有任務執行則該執行緒結束。見runWoker和getTask方法的程式碼。 if (workerAdded) { t.start();// 最終執行的是ThreadPoolExecutor的runWoker方法 workerStarted = true; } } } finally { // 執行緒啟動失敗,則從wokers中移除w並遞減wokerCount if (!workerStarted) // 遞減wokerCount會觸發tryTerminate方法 addWorkerFailed(w); } return workerStarted; }View Code
runWorker
任務新增成功後實際執行的是runWorker
這個方法,這個方法非常重要,簡單來說它做的就是:
- 第一次啟動會執行初始化傳進來的任務firstTask;
- 然後會從workQueue中取任務執行,如果佇列為空則等待keepAliveTime這麼長時間。
final void runWorker(Worker w) { Thread wt = Thread.currentThread(); Runnable task = w.firstTask; w.firstTask = null; // Worker的建構函式中抑制了執行緒中斷setState(-1),所以這裡需要unlock從而允許中斷 w.unlock(); // 用於標識是否異常終止,finally中processWorkerExit的方法會有不同邏輯 // 為true的情況:1.執行任務丟擲異常;2.被中斷。 boolean completedAbruptly = true; try { // 如果getTask返回null那麼getTask中會將workerCount遞減,如果異常了這個遞減操作會在processWorkerExit中處理 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 { // 和beforeExecute一樣,留給子類去過載 afterExecute(task, thrown); } } finally { task = null; w.completedTasks++; w.unlock(); } } completedAbruptly = false; } finally { // 結束執行緒的一些清理工作 processWorkerExit(w, completedAbruptly); } }View Code
getTask
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. // 1.rs > SHUTDOWN 所以rs至少等於STOP,這時不再處理佇列中的任務 // 2.rs = SHUTDOWN 所以rs>=STOP肯定不成立,這時還需要處理佇列中的任務除非佇列為空 // 這兩種情況都會返回null讓runWoker退出while迴圈也就是當前執行緒結束了,所以必須要decrement // wokerCount if (rs >= SHUTDOWN && (rs >= STOP || workQueue.isEmpty())) { // 遞減workerCount值 decrementWorkerCount(); return null; } // 標記從佇列中取任務時是否設定超時時間 boolean timed; // Are workers subject to culling? // 1.RUNING狀態 // 2.SHUTDOWN狀態,但佇列中還有任務需要執行 for (;;) { int wc = workerCountOf(c); // 1.core thread允許被超時,那麼超過corePoolSize的的執行緒必定有超時 // 2.allowCoreThreadTimeOut == false && wc > // corePoolSize時,一般都是這種情況,core thread即使空閒也不會被回收,只要超過的執行緒才會 timed = allowCoreThreadTimeOut || wc > corePoolSize; // 從addWorker可以看到一般wc不會大於maximumPoolSize,所以更關心後面半句的情形: // 1. timedOut == false 第一次執行迴圈, 從佇列中取出任務不為null方法返回 或者 // poll出異常了重試 // 2.timeOut == true && timed == // false:看後面的程式碼workerQueue.poll超時時timeOut才為true, // 並且timed要為false,這兩個條件相悖不可能同時成立(既然有超時那麼timed肯定為true) // 所以超時不會繼續執行而是return null結束執行緒。(重點:執行緒是如何超時的???) if (wc <= maximumPoolSize && !(timedOut && timed)) break; // workerCount遞減,結束當前thread if (compareAndDecrementWorkerCount(c)) return null; c = ctl.get(); // Re-read ctl // 需要重新檢查執行緒池狀態,因為上述操作過程中執行緒池可能被SHUTDOWN if (runStateOf(c) != rs) continue retry; // else CAS failed due to workerCount change; retry inner loop } try { // 1.以指定的超時時間從佇列中取任務 // 2.core thread沒有超時 Runnable r = timed ? workQueue.poll(keepAliveTime, TimeUnit.NANOSECONDS) : workQueue.take(); if (r != null) return r; timedOut = true;// 超時 } catch (InterruptedException retry) { timedOut = false;// 執行緒被中斷重試 } } }View Code
processWorkerExit
執行緒退出會執行這個方法做一些清理工作。
private void processWorkerExit(Worker w, boolean completedAbruptly) { // 正常的話再runWorker的getTask方法workerCount已經被減一了 if (completedAbruptly) decrementWorkerCount(); final ReentrantLock mainLock = this.mainLock; mainLock.lock(); try { // 累加執行緒的completedTasks completedTaskCount += w.completedTasks; // 從執行緒池中移除超時或者出現異常的執行緒 workers.remove(w); } finally { mainLock.unlock(); } // 嘗試停止執行緒池 tryTerminate(); int c = ctl.get(); // runState為RUNNING或SHUTDOWN if (runStateLessThan(c, STOP)) { // 執行緒不是異常結束 if (!completedAbruptly) { // 執行緒池最小空閒數,允許core thread超時就是0,否則就是corePoolSize int min = allowCoreThreadTimeOut ? 0 : corePoolSize; // 如果min == 0但是佇列不為空要保證有1個執行緒來執行佇列中的任務 if (min == 0 && !workQueue.isEmpty()) min = 1; // 執行緒池還不為空那就不用擔心了 if (workerCountOf(c) >= min) return; // replacement not needed } // 1.執行緒異常退出 // 2.執行緒池為空,但是佇列中還有任務沒執行,看addWoker方法對這種情況的處理 addWorker(null, false); } }View Code
tryTerminate
processWorkerExit方法中會嘗試呼叫tryTerminate來終止執行緒池。這個方法在任何可能導致執行緒池終止的動作後執行:比如減少wokerCount或SHUTDOWN狀態下從佇列中移除任務。
final void tryTerminate() { for (;;) { int c = ctl.get(); // 以下狀態直接返回: // 1.執行緒池還處於RUNNING狀態 // 2.SHUTDOWN狀態但是任務佇列非空 // 3.runState >= TIDYING 執行緒池已經停止了或在停止了 if (isRunning(c) || runStateAtLeast(c, TIDYING) || (runStateOf(c) == SHUTDOWN && !workQueue.isEmpty())) return; // 只能是以下情形會繼續下面的邏輯:結束執行緒池。 // 1.SHUTDOWN狀態,這時不再接受新任務而且任務佇列也空了 // 2.STOP狀態,當呼叫了shutdownNow方法 // workerCount不為0則還不能停止執行緒池,而且這時執行緒都處於空閒等待的狀態 // 需要中斷讓執行緒“醒”過來,醒過來的執行緒才能繼續處理shutdown的訊號。 if (workerCountOf(c) != 0) { // Eligible to terminate // runWoker方法中w.unlock就是為了可以被中斷,getTask方法也處理了中斷。 // ONLY_ONE:這裡只需要中斷1個執行緒去處理shutdown訊號就可以了。 interruptIdleWorkers(ONLY_ONE); return; } final ReentrantLock mainLock = this.mainLock; mainLock.lock(); try { // 進入TIDYING狀態 if (ctl.compareAndSet(c, ctlOf(TIDYING, 0))) { try { // 子類過載:一些資源清理工作 terminated(); } finally { // TERMINATED狀態 ctl.set(ctlOf(TERMINATED, 0)); // 繼續awaitTermination termination.signalAll(); } return; } } finally { mainLock.unlock(); } // else retry on failed CAS } }View Code
shutdown和shutdownNow
shutdown這個方法會將runState置為SHUTDOWN
,會終止所有空閒的執行緒。
public void shutdown() { final ReentrantLock mainLock = this.mainLock; mainLock.lock(); try { checkShutdownAccess(); // 執行緒池狀態設為SHUTDOWN,如果已經至少是這個狀態那麼則直接返回 advanceRunState(SHUTDOWN); // 注意這裡是中斷所有空閒的執行緒:runWorker中等待的執行緒被中斷 → 進入processWorkerExit → // tryTerminate方法中會保證佇列中剩餘的任務得到執行。 interruptIdleWorkers(); onShutdown(); // hook for ScheduledThreadPoolExecutor } finally { mainLock.unlock(); } tryTerminate(); }
shutdownNow方法將runState置為STOP。和shutdown方法的區別,這個方法會終止所有的執行緒。
public List<Runnable> shutdownNow() { List<Runnable> tasks; final ReentrantLock mainLock = this.mainLock; mainLock.lock(); try { checkShutdownAccess(); // STOP狀態:不再接受新任務且不再執行佇列中的任務。 advanceRunState(STOP); // 中斷所有執行緒 interruptWorkers(); // 返回佇列中還沒有被執行的任務。 tasks = drainQueue(); } finally { mainLock.unlock(); } tryTerminate(); return tasks; }
主要區別在於shutdown呼叫的是interruptIdleWorkers
這個方法,而shutdownNow實際呼叫的是Worker類的interruptIfStarted
方法:
private void interruptIdleWorkers(boolean onlyOne) { final ReentrantLock mainLock = this.mainLock; mainLock.lock(); try { for (Worker w : workers) { Thread t = w.thread; // w.tryLock能獲取到鎖,說明該執行緒沒有在執行,因為runWorker中執行任務會先lock, // 因此保證了中斷的肯定是空閒的執行緒。 if (!t.isInterrupted() && w.tryLock()) { try { t.interrupt(); } catch (SecurityException ignore) { } finally { w.unlock(); } } if (onlyOne) break; } } finally { mainLock.unlock(); } }
void interruptIfStarted() { Thread t; // 初始化時state == -1 if (getState() >= 0 && (t = thread) != null && !t.isInterrupted()) { try { t.interrupt(); } catch (SecurityException ignore) { } } }
這就是前面提到的Woker類實現AQS的主要作用。
注意:shutdown方法可能會在finalize被隱式的呼叫。
這篇部落格基本都是程式碼跟註釋,所以如果不是分析ThreadPoolExecutor
原始碼的話看起來會非常無聊。
相關推薦
Java併發包原始碼學習之執行緒池(一)ThreadPoolExecutor原始碼分析
Java中使用執行緒池技術一般都是使用Executors這個工廠類,它提供了非常簡單方法來建立各種型別的執行緒池: public static ExecutorService newFixedThreadPool(int nThreads) public static ExecutorService
java併發學習--執行緒池(一)
關於java中的執行緒池,我一開始覺得就是為了避免頻繁的建立和銷燬執行緒吧,先建立一定量的執行緒,然後再進行復用。但是要具體說一下如何做到的,自己又說不出一個一二三來了,這大概就是自己的學習習慣流於表面,不經常深入的結果吧。所以這裡決定系統的學習一下執行緒池的相關知識。 自己稍微總結了一下,
原始碼學習之執行緒池
大家面試過程中肯定被問道過執行緒池。為什麼要使用執行緒池呢?因為在系統中頻繁建立執行緒會造成很大的CPU消耗。而且用完的執行緒要等待GC回收也會造成消耗。 下面我們就來學習下最常用的執行緒池 ThreadPoolExecutor, 首先先來看看它的構造方法: public ThreadPo
Java多執行緒之執行緒池(二)
java.util.concurrent包是jdk1.5以後使用的執行緒庫,在jdk1.5之前主要使用java.lang和java.util中的類實現 package three.day.thread; import java.util.Random; import ja
Java多執行緒之執行緒池(五)
本例主要演示如何建立一個用於排程定時任務的執行緒池 package three.day.thread.my; import java.util.Random; import java.util.concurrent.Executors; import java.util.
java併發——執行緒池(一)執行機制和如何使用
合理利用執行緒池能夠帶來三個好處。 1、第一:降低資源消耗。通過重複利用已建立的執行緒降低執行緒建立和銷燬造成的消耗。 2、第二:提高響應速度。當任務到達時,任務可以不需要的等到執行緒建立就能立即執行。 3、第三:提高執行緒的可管理性。執
spring原始碼學習之路---IOC初探(一)
首先把spring原始碼匯入,怎麼匯入百度下。 首先我們來說一下IOC,IOC是spring最核心的理念,包括AOP也要屈居第二,那麼IOC到底是什麼呢,四個字,控制反轉。 網上有不少是這麼解釋IOC的,說IOC是將物件的建立和依賴關係交給容器,這句話我相信不少人都知道,在我個人的理解
java-執行緒池(一)
一、為什麼使用執行緒池 重用執行緒池中的使用,減少建立線和銷燬程的的資源消耗和提高效能。 可以對執行緒進行管理與維護 二、執行緒池的建立 執行緒池的建立可以使用Executors類中的方法建立,可以參考常用的四種執行緒池的建立,下面來看J.U.C包下的T
Android執行緒池(四)ThreadPoolExecutor類原始碼解析
使用ThreadPoolExecutor private final int CORE_POOL_SIZE = 4;//核心執行緒數 private final int MAX_POOL_SIZE = 5;//最大執行緒數 priv
深入分析執行緒池(二)—ThreadPoolExecutor常用方法
這4個類就是我們的主線。這裡我只顯示了public方法詳細介紹ThreadPoolExecutor的方法:方法shutdown() 和 shutdownNow() shutdown :使當前未執行的執行緒繼續執行,而不再新增新的任務Task,該方法不會阻塞。 sh
Android執行緒與執行緒池(一)
前言,學習安卓很久了,一直也沒有學部落格的習慣,下決心從今天開始要養成寫部落格總結學習經驗的好習慣! 一.Android中執行緒與執行緒池的簡介 在Android中執行緒主要可以分為兩大類:一個用於處理介面相關與使用者互動的執行緒-主執行緒;一個用於處理耗時任務-子執行緒
六、執行緒池(一)
### 執行緒池 通過建立池可以有效的利用系統資源,節約系統性能。Java 中的執行緒池就是一種非常好的實現,從 JDK1.5 開始 Java 提供了一個執行緒工廠 Executors 用來生成執行緒池,通過 Executors 可以方便的生成不同型別的執行緒池。 ### 執行緒池的優點 - 降低資源消耗。
《java併發程式設計實戰》之 執行緒安全性
1.執行緒安全性 當多個執行緒訪問某個類時,不管執行時環境採用何種排程方式或者這些執行緒將如何交替執行,並且在主調程式碼中不需要任何額外的同步或協同,這個類都能表現出正確的行為,那麼這個類就是執行緒安全的。 無狀態物件一定是執行緒安全的,何為無狀態,就是類中不包含任何域,也不包含各種其
Java併發程式設計:4種執行緒池和緩衝佇列BlockingQueue
一. 執行緒池簡介 1. 執行緒池的概念: 執行緒池就是首先建立一些執行緒,它們的集合稱為執行緒池。使用執行緒池可以很好地提高效能,執行緒池在系統啟動時即建立大量空閒的執行緒,程式將一個任務傳給執行緒池,執行緒池就會啟動一
Java多執行緒之執行緒排程(二)
(一)執行緒優先順序 執行緒優先順序用1~10表示,10表示優先順序最高,預設值是5.每個優先順序對應一個Thread類的公用靜態常量。如 public static final int MIN_PRIORITY = 1; public static final int NO
Java執行緒池架構(一)原理和原始碼解析
在前面介紹JUC的文章中,提到了關於執行緒池Execotors的建立介紹,在文章:《java之JUC系列-外部Tools》中第一部分有詳細的說明,請參閱; 文章中其實說明了外部的使用方式,但是沒有說內部是如何實現的,為了加深對實現的理解,在使用中可以放心,我們這裡將做原始碼解析以及反饋到原理上
Java併發程式設計札記-(六)JUC執行緒池-01概述
前面的例子中總是需要執行緒時就建立,不需要就銷燬它。但頻繁建立和銷燬執行緒是很耗資源的,在併發量較高的情況下頻繁建立和銷燬執行緒會降低系統的效率。執行緒池可以通過重複利用已建立的執行緒降低執行緒建立和銷
Java併發程式設計中四種執行緒池及自定義執行緒使用教程
引言 通過前面的文章,我們學習了Executor框架中的核心類ThreadPoolExecutor ,對於執行緒池的核心排程機制有了一定的瞭解,並且成功使用ThreadPoolExecutor 建立了執行緒池。 而在Java中,除了ThreadPoolExecutor ,Executor框
21、Java併發類庫提供的執行緒池有哪幾種? 分別有什麼特點?(高併發程式設計----7)
目錄 今天我要問你的問題是,Java 併發類庫提供的執行緒池有哪幾種? 分別有什麼特點? 典型回答 考點分析 知識擴充套件 下面我就從原始碼角度,分析執行緒池的設計與實現,我將主要圍繞最基礎的 ThreadPoolExecutor 原始碼。 進一步分析,執行緒池既然
Java併發程式設計的藝術(十)——執行緒池(1)
執行緒池的作用 減少資源的開銷 減少了每次建立執行緒、銷燬執行緒的開銷。 提高響應速度 每次請求到來時,由於執行緒的建立已經完成,故可以直接執行任務,因此提高了響應速度。 提高執行緒的可管理性 執行緒是一種稀缺資源,若不加以限制,不僅會佔用大量資源