【Android 异步操作】线程池 ( 线程池 reject 拒绝任务 | 线程池 addWorker 添加任务 )
文章目錄
- 一、線程池 reject 拒絕任務
- 二、線程池 addWorker 添加任務
在上一篇博客 【Android 異步操作】線程池 ( 線程池 execute 方法源碼解析 ) 中 , 講解 線程池 ThreadPoolExecutor 的 execute 方法時 , 有兩個重要的核心方法 ;
兩個核心的操作 :
- 添加任務 : addWorker(command, true) , 第二個參數為 true 是添加核心線程任務 , 第二個參數為 false 是添加非核心線程任務 ;
- 拒絕任務 : reject(command)
本博客中研究 拒絕任務 reject 方法的細節 ;
一、線程池 reject 拒絕任務
在 ThreadPoolExecutor 線程池中 , void reject(Runnable command) 方法 , 主要是調用了 RejectedExecutionHandler handler 的 rejectedExecution 方法 ;
該 handler 可以在如下 構造函數中傳入 , 如下構造函數中的最后一個參數 ;
public ThreadPoolExecutor(int corePoolSize,int maximumPoolSize,long keepAliveTime,TimeUnit unit,BlockingQueue<Runnable> workQueue,ThreadFactory threadFactory,RejectedExecutionHandler handler) {部分相關代碼示例 :
public class ThreadPoolExecutor extends AbstractExecutorService {/*** 當線程池任務飽和 , 或線程池關閉 , 使用該 Handler 處理拒絕任務異常情況 ;*/private volatile RejectedExecutionHandler handler;/*** 在該構造函數中 , 可以傳入 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;}/*** 拒絕執行給定命令的處理 */final void reject(Runnable command) {handler.rejectedExecution(command, this);} }自定義 RejectedExecutionHandler 處理拒絕任務的情況 ;
實現 rejectedExecution 方法 , 當 線程池任務隊列飽和 , 或者 沒有空閑線程 時 , 線程池被關閉 時 , 導致線程池的任務隊列無法接受該任務時 , 會調用該方法
/*** 處理添加任務失敗情況的 handler * 用戶可以自定義該接口 */ public interface RejectedExecutionHandler {/*** * 無法接受任務時執行該方法 ;* 當線程池任務隊列飽和 , 或者沒有空閑線程時 , 線程池被關閉時 , 會調用該方法** 該方法可能會觸發 RejectedExecutionException 異常 , 用戶需要捕獲并處理該異常** @param r 被拒絕的任務* @param executor 嘗試執行該任務的執行者* @throws RejectedExecutionException 如果沒有補救方法, 拋出該異常*/void rejectedExecution(Runnable r, ThreadPoolExecutor executor); }
二、線程池 addWorker 添加任務
檢查一個新的工作者 ( Worker ) 是否可以被添加 , 根據當前的 線程池狀態 , 和 給定的核心線程數 , 最大線程數 等判定 ;
如果可以添加 , 那么先 調整 工作者 ( Worker ) 的個數 , 然后 創建新的 工作者 ( Worker ) , 并 將參數中的 Runnable firstTask 設置為第一個任務 ;
如果線程池停止或關閉 , 返回 false ;
如果線程創建失敗 , 不管是線程工廠返回空 , 還是出現 OOM , 直接退出 ;
如果當前的 線程個數少于 核心線程數 , 或者當前的 任務數已滿 , 則必須創建 工作者 ( Worker ) , 并執行第一個初始任務 ,
public class ThreadPoolExecutor extends AbstractExecutorService {/*** 檢查一個新的工作者是否可以被添加 , 根據當前的線程池狀態 , 和給定的核心線程數 , 最大線程數等判定 ;* 如果可以添加 , 那么先調整 工作者 ( Worker ) 的個數 , 然后創建新的 工作者 ( Worker ) , * 并將參數中的 Runnable firstTask 設置為第一個任務 ; * 如果線程池停止或關閉 , 返回 false ; * 如果線程創建失敗 , 不管是線程工廠返回空 , 還是出現 OOM , 直接退出 ; ** 第一個運行的任務 ; * 如果當前的線程個數少于 核心線程數 , 或者當前的任務數已滿 , * 必須創建 工作者 ( Worker ) , 并執行第一個初始任務 , ** @param core 如果設置為 true , 必須使用核心線程綁定 * @return true if successful*/private boolean addWorker(Runnable firstTask, boolean core) {retry:// 死循環for (;;) {int c = ctl.get();int rs = runStateOf(c);// 查看隊列是否為空// 查看線程池是否 SHUTDOWN if (rs >= SHUTDOWN &&! (rs == SHUTDOWN &&firstTask == null &&! workQueue.isEmpty()))return false;// 查看線程池的線程個數 , 與 核心線程數, 最大線程數 進行各種對比// 獲取現在的線程池情況 for (;;) {int wc = workerCountOf(c);if (wc >= CAPACITY ||wc >= (core ? corePoolSize : maximumPoolSize))return false;// 如果沒有達到最大線程數 , 允許添加 if (compareAndIncrementWorkerCount(c)) // 該行代碼只是將計數器 +1break retry;c = ctl.get(); // Re-read ctlif (runStateOf(c) != rs)continue retry;// else CAS failed due to workerCount change; retry inner loop}}// 下面是添加一個線程的邏輯 boolean workerStarted = false;boolean workerAdded = false;Worker w = null;try {// 創建工作者 , 并將任務設置給該工作者 w = new Worker(firstTask);// 線程是從工作者中取出的 , 該線程是在 Worker 構造函數中使用線程工廠創建的 final Thread t = w.thread;if (t != null) {final ReentrantLock mainLock = this.mainLock;mainLock.lock();try {// Recheck while holding lock.// Back out on ThreadFactory failure or if// shut down before lock acquired.int rs = runStateOf(ctl.get());if (rs < SHUTDOWN ||(rs == SHUTDOWN && firstTask == null)) {if (t.isAlive()) // precheck that t is startablethrow new IllegalThreadStateException();// 將工作者設置給 工作者集合 workers.add(w);int s = workers.size();if (s > largestPoolSize)largestPoolSize = s;workerAdded = true;}} finally {mainLock.unlock();}// 如果添加成功 , 就會啟動 Worker 中的線程 if (workerAdded) {t.start();workerStarted = true;}}} finally {if (! workerStarted)addWorkerFailed(w);}return workerStarted;} }總結
以上是生活随笔為你收集整理的【Android 异步操作】线程池 ( 线程池 reject 拒绝任务 | 线程池 addWorker 添加任务 )的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【Android 异步操作】线程池 (
- 下一篇: 【Android 异步操作】线程池 (