原文地址:http://www.cnblogs.com/java-zhao/p/5147811.html
1、源代碼主要掌握兩個部分
- 線程池的創建:構造器
- 提交任務到線程池去執行:execute()
2、構造器
2.1、一些屬性:
/** * runState provides the main lifecyle control, taking on values: * * RUNNING -> SHUTDOWN * On invocation of shutdown(), perhaps implicitly in finalize() * (RUNNING or SHUTDOWN) -> STOP * On invocation of shutdownNow() * SHUTDOWN -> TERMINATED * When both queue and pool are empty * STOP -> TERMINATED * When pool is empty */ volatile int runState; static final int RUNNING = 0;//接收新的任務,會處理隊列中的任務 static final int SHUTDOWN = 1;//不接收新的任務,但是會處理隊列中的任務 static final int STOP = 2;//不接收新的任務,也不會處理隊列中的任務,而且還會中斷正在執行的任務 static final int TERMINATED = 3;//STOP+中止所有線程 private final BlockingQueue<Runnable> workQueue;//隊列 /** * 對poolSize, corePoolSize, maximumPoolSize, runState, and workers set上鎖 */ private final ReentrantLock mainLock = new ReentrantLock(); /** * 支持awaitTermination的等待條件 */ private final Condition termination = mainLock.newCondition(); /** * pool中的所有工作線程集合;僅僅在持有mainLock的時候才允許被訪問 */ private final HashSet<Worker> workers = new HashSet<Worker>(); private volatile long keepAliveTime; /** * false(默認):當核心線程處於閒置狀態時,也會存活 * true:核心線程使用keepAliveTime來決定自己的存活狀態 */ private volatile boolean allowCoreThreadTimeOut; /** * Core pool size,僅僅在持有mainLock的時候才允許被更新, * 因爲是volatile允許併發讀(即使是在更新的過程中) */ private volatile int corePoolSize; /** * Maximum pool size, 其他同上 */ private volatile int maximumPoolSize; /** * Current pool size, 其他同上 */ private volatile int poolSize; /** * 回絕處理器 */ private volatile RejectedExecutionHandler handler; /** * 所有的線程都通過這個線程工廠的addThread方法來創建。 */ private volatile ThreadFactory threadFactory; /** * Tracks largest attained pool size. */ private int largestPoolSize; /** * 已經完成的任務數.僅僅在工作線程被終結的時候這個數字纔會被更新 */ private long completedTaskCount; /** * 默認的回絕處理器(回絕任務並拋出異常) */ private static final RejectedExecutionHandler defaultHandler = new AbortPolicy();
說明:因爲屬性不多,這裏列出了全部屬性。
2.2、構造器:
public ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue) { this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, Executors.defaultThreadFactory(), defaultHandler); } public ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, ThreadFactory threadFactory) { this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, threadFactory, defaultHandler); } public ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, RejectedExecutionHandler handler) { this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, Executors.defaultThreadFactory(), handler); } public ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, ThreadFactory threadFactory, RejectedExecutionHandler handler) { /* * 檢查參數 */ if (corePoolSize < 0 || maximumPoolSize <= 0 || maximumPoolSize < corePoolSize || keepAliveTime < 0) throw new IllegalArgumentException(); if (workQueue == null || threadFactory == null || handler == null) throw new NullPointerException(); /* * 初始化值 */ this.corePoolSize = corePoolSize; this.maximumPoolSize = maximumPoolSize; this.workQueue = workQueue; this.keepAliveTime = unit.toNanos(keepAliveTime);//轉成納秒 this.threadFactory = threadFactory; this.handler = handler; }
說明:4個構造器(1個5參+2個6參+1個7參)
注意:默認情況下,構造器只會初始化參數,不會提前構建好線程
建議:構造器參數衆多,建議使用構建器模式,關於構建器模式的實際使用範例,請參照《第二章 Google guava cache源碼解析1--構建緩存器》
構造器中默認線程工廠的創建:Executors中的方法
public static ThreadFactory defaultThreadFactory() { return new DefaultThreadFactory(); } /** * 默認的線程工廠 */ static class DefaultThreadFactory implements ThreadFactory { static final AtomicInteger poolNumber = new AtomicInteger(1);//池數量 final ThreadGroup group;//線程組 final AtomicInteger threadNumber = new AtomicInteger(1);//線程數量 final String namePrefix; /* * 創建默認的線程工廠 */ DefaultThreadFactory() { SecurityManager s = System.getSecurityManager(); group = (s != null)? s.getThreadGroup() : Thread.currentThread().getThreadGroup(); namePrefix = "pool-" + poolNumber.getAndIncrement() + "-thread-"; } /* * 創建一個新的線程 */ public Thread newThread(Runnable r) { Thread t = new Thread(group, r, namePrefix + threadNumber.getAndIncrement(),//新線程的名字 0); /* * 將後臺線程設置爲應用線程 */ if (t.isDaemon()) t.setDaemon(false); /* * 將線程的優先級全部設置爲NORM_PRIORITY */ if (t.getPriority() != Thread.NORM_PRIORITY) t.setPriority(Thread.NORM_PRIORITY); return t; } }
說明,其中的newThread()方法會在第三部分用到。
3、提交任務的線程池去執行execute(Runnable command)
public void execute(Runnable command) { if (command == null) throw new NullPointerException(); /** * 這一塊兒就是整個工作機理的部分(代碼比較精緻) * 1、addIfUnderCorePoolSize * 1)如果當前線程數poolSize<核心線程數corePoolSize並且pool的狀態爲RUNNING, * 1.1)先獲取鎖 * 1.2)根據傳入的任務firstTask創建一個Work對象,在該對象中編寫了run()方法,在該run()方法中會真正的去執行firstTask的run() * 說明:關於Work對象run部分的內容,查看Work內部類的run()方法上邊的註釋以及與其相關方法的註釋 * 1.3)通過線程工廠與上邊創建出來的work對象w創建新的線程t,將w加入工作線程集合, * 然後啓動線程t,之後就會自動執行w中的run(),w中的run()又會調用firstTask的run(),即處理真正的業務邏輯 * * 2、如果poolSize>=corePoolSize或者上邊的執行失敗了 * 1)如果pool的狀態處於RUNNING,將該任務入隊(offer(command)) * 如果入隊後,pool的狀態不是RUNNING了或者池中的線程數爲0了,下邊的邏輯具體去查看註釋 * 2)addIfUnderMaximumPoolSize(同addIfUnderCorePoolSize) * 如果增加線程也不成功,則回絕任務。 * */ if (poolSize >= corePoolSize || !addIfUnderCorePoolSize(command)) { if (runState == RUNNING && workQueue.offer(command)) { if (runState != RUNNING || poolSize == 0) ensureQueuedTaskHandled(command); } else if (!addIfUnderMaximumPoolSize(command)) reject(command); // is shutdown or saturated } }
3.1、addIfUnderCorePoolSize(Runnable firstTask)
/** * 創建並且啓動一個新的線程來處理任務 * 1、其第一個任務就是傳入的firstTask參數 * 2、該方法僅僅用於當前線程數小於核心線程數並且pool沒有被關掉的時候 */ private boolean addIfUnderCorePoolSize(Runnable firstTask) { Thread t = null; final ReentrantLock mainLock = this.mainLock; mainLock.lock();//獲取鎖 try { if (poolSize < corePoolSize && runState == RUNNING) t = addThread(firstTask);//創建新線程 } finally { mainLock.unlock();//釋放鎖 } return t != null; }
addThread(Runnable firstTask)
private Thread addThread(Runnable firstTask) { Worker w = new Worker(firstTask);//構造一個work Thread t = threadFactory.newThread(w);//創建線程 boolean workerStarted = false; if (t != null) {// if (t.isAlive()) //如果t線程已經啓動了,而且還沒有死亡 throw new IllegalThreadStateException(); w.thread = t; workers.add(w);//將w工作線程加入workers線程池 int nt = ++poolSize;//當前的池數量+1 if (nt > largestPoolSize) largestPoolSize = nt; try { t.start();//啓動線程 workerStarted = true; } finally { if (!workerStarted)//啓動線程沒有成功 workers.remove(w);//將w從workers集合中刪除 } } return t; }
newThread(Runnable r)
該方法在構建上邊的默認線程工廠部分已經說過了。
Work內部類:
/** * 工作線程。 */ private final class Worker implements Runnable { /** * 在每一個任務的執行前後都會獲取和釋放runLock。 * 該鎖只要是爲了防止中斷正在執行任務的work線程 */ private final ReentrantLock runLock = new ReentrantLock(); /** * Initial task to run before entering run loop. * 1、Possibly null. */ private Runnable firstTask; /** * 每個work線程完成的任務總量 * accumulated into completedTaskCount upon termination. */ volatile long completedTasks; Thread thread; /** * 該work中的線程是不是確實正在執行了run() */ volatile boolean hasRun = false; Worker(Runnable firstTask) { this.firstTask = firstTask; } /* * true:已經有線程持有了該鎖 */ boolean isActive() { return runLock.isLocked(); } private void runTask(Runnable task) { final ReentrantLock runLock = this.runLock; runLock.lock();//獲取鎖runLock try { /* * 如果pool狀態爲STOP或TERMINATED,確保線程被打斷; * 如果不是,確保線程不要被打斷 */ if ((runState >= STOP || (Thread.interrupted() && runState >= STOP)) && hasRun) thread.interrupt(); /* * 確保afterExecute會被執行僅僅當任務完成了(try)或拋出了異常(catch) */ boolean ran = false; beforeExecute(thread, task);//執行任務的run()方法之前要執行的操作 try { task.run();//執行線程的run()方法 ran = true; afterExecute(task, null);//執行任務的run()方法之後要執行的操作 ++completedTasks; } catch (RuntimeException ex) { if (!ran) afterExecute(task, ex); throw ex; } } finally { runLock.unlock();//釋放鎖runLock } } /** * Main run loop * 運行當前任務task,運行結束後,嘗試獲取隊列中的其他任務, * 如果最後通過各種方式都獲取不到,就回收該線程,如果獲取到了,就用該線程繼續執行接下來的任務 * 最後,當獲取不到任何任務去執行時,就將該線程從works線程集合中刪除掉 */ public void run() { try { hasRun = true; Runnable task = firstTask; firstTask = null; while (task != null || (task = getTask()) != null) { runTask(task);//運行該任務 task = null; } } finally { workerDone(this);//將該線程從works集合中刪除 } } }
說明:這裏列出了該內部類的全部屬性和常用方法。
getTask()
/** * 獲取下一個worker線程將要運行的任務 * Gets the next task for a worker thread to run. */ Runnable getTask() { for (;;) {//無限循環 try { int state = runState; if (state > SHUTDOWN) return null; Runnable r; if (state == SHUTDOWN) // Help drain queue r = workQueue.poll();//處理queue中的任務 //下面的runState==RUNNING else if (poolSize > corePoolSize || allowCoreThreadTimeOut) //從隊頭獲取任務,如果沒有任務,等待keepAliveTime的時間 r = workQueue.poll(keepAliveTime, TimeUnit.NANOSECONDS); else //從隊頭獲取任務,如果沒有任務,阻塞等待 r = workQueue.take(); if (r != null) return r; if (workerCanExit()) {//允許回收獲取任務失敗的線程 if (runState >= SHUTDOWN) // Wake up others interruptIdleWorkers();//中斷閒置的work線程 return null; } // Else retry } catch (InterruptedException ie) { // On interruption, re-check runState } } }
workerCanExit()
/** * 檢測一個獲取任務失敗的work線程是否可以退出了。 * 出現下面三種情況,work線程就會死亡。 * 1、如果pool的狀態爲STOP或TERMINATED * 2、隊列爲空 * 3、允許回收核心線程並且池中的線程數大於1和corePoolSize的最大值 */ private boolean workerCanExit() { final ReentrantLock mainLock = this.mainLock; mainLock.lock(); boolean canExit; try { canExit = runState >= STOP || workQueue.isEmpty() || (allowCoreThreadTimeOut && poolSize > Math.max(1, corePoolSize)); } finally { mainLock.unlock(); } return canExit; }
workerDone(Worker w)
void workerDone(Worker w) { final ReentrantLock mainLock = this.mainLock; mainLock.lock(); try { completedTaskCount += w.completedTasks; workers.remove(w);//從workers集合中刪除該線程 if (--poolSize == 0)//如果池中的線程數爲0 tryTerminate(); } finally { mainLock.unlock(); } }
3.2、ensureQueuedTaskHandled(Runnable command)
/** * 在一個task入隊之後重新檢查state。 * 當一個task入隊後,pool的state發生了變化,該方法就會被調用。 * 如果一個task入隊的同時,shutdownNow方法發生了調用,該方法就必須從隊列中移除並回絕 * 否則該方法會保證至少有一個線程來處理入隊的task */ private void ensureQueuedTaskHandled(Runnable command) { final ReentrantLock mainLock = this.mainLock; mainLock.lock(); boolean reject = false; Thread t = null; try { int state = runState; if (state != RUNNING && workQueue.remove(command)) reject = true; else if (state < STOP && poolSize < Math.max(corePoolSize, 1) && !workQueue.isEmpty()) t = addThread(null); } finally { mainLock.unlock(); } if (reject) reject(command); }
3.3、addIfUnderMaximumPoolSize(Runnable firstTask)
private boolean addIfUnderMaximumPoolSize(Runnable firstTask) { Thread t = null; final ReentrantLock mainLock = this.mainLock; mainLock.lock(); try { if (poolSize < maximumPoolSize && runState == RUNNING) t = addThread(firstTask); } finally { mainLock.unlock(); } return t != null; }
說明:該方法的其他方法與addIfUnderCorePoolSize(Runnable firstTask)一樣。
3.4、reject(Runnable command)
void reject(Runnable command) { handler.rejectedExecution(command, this); }
public static class AbortPolicy implements RejectedExecutionHandler { public AbortPolicy() { } /** 直接拋異常 */ public void rejectedExecution(Runnable r, ThreadPoolExecutor e) { throw new RejectedExecutionException(); } }