接著說worker線程是如何工作的。ThreadPoolExecutor有一個成員類叫Worker,所起到的作用就是線程池worker線程的作用。
PRivate final class Worker extends AbstractQueuedSynchronizer implements Runnable
這里AbstractQueuedSynchronizer的作用是使Worker具有鎖的功能,在執行任務時,會把Worker鎖住,這個時候就無法中斷Worker。Worker空閑時候是線程池可以通過獲取鎖,改變Worker的某些狀態,在此期間因為鎖被占用,Worker就是不會執行任務的。
Worker工作的邏輯在ThreadPoolExecutor#runWorker方法中
public void run() { runWorker(this); }
因此轉到runWorker方法:
final void runWorker(Worker w) { Runnable task = w.firstTask; w.firstTask = null; boolean completedAbruptly = true; try { // 執行分配的任務或者從BlockingQueue中等待獲取任務 while (task != null || (task = getTask()) != null) { w.lock(); clearInterruptsForTaskRun(); try { // 執行任務之前的工作 beforeExecute(w.thread, task); Throwable thrown = null; // 執行任務,如果發生異常,該Worker就不會再繼續執行任務 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 { // 任務執行完的工作 afterExecute(task, thrown); } } finally { task = null; w.completedTasks++; w.unlock(); } } completedAbruptly = false; } finally { // Worker不再執行任務的處理,completedAbruptly為false // 表示正常結束,否則表示執行任務出錯。 processWorkerExit(w, completedAbruptly); } }
來看看processWorkerExit,重點看看執行任務發生異常時該如何處理
private void processWorkerExit(Worker w, boolean completedAbruptly) { // 發生異常,首先要更新Worker數量 if (completedAbruptly) decrementWorkerCount(); // 移除這個Worker final ReentrantLock mainLock = this.mainLock; mainLock.lock(); try { completedTaskCount += w.completedTasks; workers.remove(w); } finally { mainLock.unlock(); } // 嘗試停止線程池,正常運行的線程池調用該方法不會有任何動作 tryTerminate(); int c = ctl.get(); // 如果線程池沒有被關閉的話, if (runStateLessThan(c, STOP)) { // Worker不是異常退出,檢查worker線程數是不是小于最小值 // 這個最小值分為幾種情況: // 1. allowCoreThreadTimeOut(JDK6新加)表示是否允許線程池在超 // 過一定時間沒有收到任務后退出,這種情況下,最小值為0,因為如果如 // 果一直沒有任何任務,worker線程數是0 // 2. 最小值為corePoolSize,因為corePoolSize可能為0,因此這種情況 // 下,如果有任務的話必然會有Worker,因此最小值為1 if (!completedAbruptly) { int min = allowCoreThreadTimeOut ? 0 : corePoolSize; if (min == 0 && ! workQueue.isEmpty()) min = 1; if (workerCountOf(c) >= min) return; } // 如果Worker線程數小于最小值,新建一個Worker線程 addWorker(null, false); } }
這篇文章主要講述了Worker線程的工作原理,接下里會講線程池是如何進行狀態切換的。
新聞熱點
疑難解答