這一部分來說說線程池如何進行狀態控制,即線程池的開啟和關閉。
先來說說線程池的開啟,這部分來看ThreadPoolExecutor構造方法:
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; }
可以看到,盡管設定了corePoolSize,也就是Worker線程的數量,但是線程池開啟的時候,默認是沒有創建這些Worker線程的,但是ThreadPoolExecutor提供了PRestartAllCoreThreads方法來開啟所有的預設的Worker線程,以及prestartCoreThread嘗試開啟一個預設的Worker線程。
這里重點說說handler,也就是RejectedExecutionHandler,拒絕任務的處理類,ThreadPoolExecutor提供四種策略:
1. CallerRunsPolicy
該策略會在ThreadPoolExecutor沒有關閉的情況,依舊運行任務
2. AbortPolicy
該策略會拋出一個RejectedExecutionException
3. DiscardPolicy
該策略直接忽略該任務,不會有任何動作
4. DiscardOldestPolicy
該策略會在ThreadPoolExecutor沒有關閉的情況,丟棄下一個將要執行的任務,把該任務加入到執行隊列。
接下來說說關閉,ThreadPoolExecutor提供了shutdown和shutdownNow兩種方式,從字面上就能看出區別,后者會嘗試結束正在運行的任務。
先來看shutdown:
public void shutdown() { final ReentrantLock mainLock = this.mainLock; mainLock.lock(); try { checkShutdownaccess(); advanceRunState(SHUTDOWN); interruptIdleWorkers(); onShutdown(); // ScheduledThreadPoolExecutor的回調方法 } finally { mainLock.unlock(); } tryTerminate(); }
再看shutdownNow:
public List<Runnable> shutdownNow() { List<Runnable> tasks; final ReentrantLock mainLock = this.mainLock; mainLock.lock(); try { checkShutdownAccess(); advanceRunState(STOP); interruptWorkers(); tasks = drainQueue(); } finally { mainLock.unlock(); } tryTerminate(); return tasks; }
兩個方法的代碼非常相似,區別在于:
1. shutdownNow的狀態設置為STOP,shutdown的狀態是SHUTDOWN
2. shutdownNow會中斷所有線程,也就是所有任務,而shutdown僅僅中斷空閑線程,不會影響正在執行的任務。
3. shutdownNow會導出未執行的任務。
兩個方法都用到的checkShutdownAccess方法主要是檢查方法調用者是否有權限中斷Worker線程。
advanceRunState方法用于設定線程的狀態,如果狀態值大于等于該狀態值則會返回。關于狀態值參看 《java.util.concurrent 包源碼閱讀》11 線程池系列之ThreadPoolExecutor 第一部分。
關于interruptIdleWorkers和interruptWorkers,在上一篇文章曾經說過Worker線程具備鎖的功能,因此可以通過tryLock來判斷Worker線程是否處于空閑狀態,這是兩個方法的區別所在。
這一部分寫的有些凌亂,各位見諒。
新聞熱點
疑難解答