【Android 异步操作】线程池 ( 线程池 execute 方法源码解析 )
文章目錄
- 一、線程池 execute 方法源碼解析
- 二、線程池 execute 方法完整源碼及注釋
一、線程池 execute 方法源碼解析
進入 ThreadPoolExecutor 中 , 查看線程池任務執行方法 public void execute(Runnable command) 的源碼 ;
用戶向線程池中提交任務時 , 主要執行了三個步驟 ,
第一步 : 核心線程數不足的情況
如果當前運行的線程 , 小于核心線程數 , 那么 創建一個新的核心線程 ,
將 傳入的任務 作為該線程的 第一個任務 .
調用 addWorker 方法 , 會原子性 檢查運行狀態和任務數量 ;
如果在 不應該添加線程的情況下 執行添加線程操作 , 就會發出錯誤警報 ;
如果該方法返回 false , 說明 當前不能添加線程 , 此時就不要執行添加線程的操作了 ;
源碼解析 : 如果當前的線程數小于核心線程數 , 則調用 addWorker(command, true) , 添加核心線程 , 第二個參數 true 表示該添加的線程是核心線程 ;
if (workerCountOf(c) < corePoolSize) {if (addWorker(command, true))return;c = ctl.get();}第二步 : 任務放入 線程池任務隊列 成功情況
如果任務被成功放入 線程池任務 隊列 , 不管我們此時是否應該添加線程 , 都需要進行 雙重驗證 ;
雙重驗證 : 添加到任務隊列 時驗證一次 , 添加到線程執行 時驗證一次 ;
可能存在這種情況 , 在上次驗證線程運行狀態之后 , 有可能 該線程就立刻被銷毀了 ;
也可能存在進入該方法后 , 線程池被銷毀的情況 ;
因此我們 反復驗證線程狀態 , 如果需要在線程停止時回滾隊列 , 如果沒有線程就創建新線程 ;
先調用 isRunning( c ) 判斷線程是否在運行中 , 只有運行狀態時 , 線程池才能接收任務 ,
先 將任務添加到隊列 中 , 調用 workQueue.offer(command) 方法實現 ,
然后又調用 isRunning(recheck) 判定該線程是否是運行狀態 ,
如果不在 , 那么調用 remove(command) 移除該命令 , 然后調用 reject(command) 拒絕執行該命令 ,
if (isRunning(c) && workQueue.offer(command)) {int recheck = ctl.get();if (! isRunning(recheck) && remove(command))reject(command);else if (workerCountOf(recheck) == 0)addWorker(null, false);}兩個核心的操作 :
- 添加任務 : addWorker(command, true) , 第二個參數為 true 是添加核心線程任務 , 第二個參數為 false 是添加非核心線程任務 ;
- 拒絕任務 : reject(command)
第三步 : 任務放入 線程池任務隊列 失敗情況
如果不能將任務放入隊列中 , 嘗試創建一個新線程 ;
如果創建線程失敗 , 說明當前線程池關閉 , 或者線程池中線程飽和 , 此時 拒絕執行該任務 ;
else if (!addWorker(command, false))reject(command);二、線程池 execute 方法完整源碼及注釋
public class ThreadPoolExecutor extends AbstractExecutorService {public void execute(Runnable command) {if (command == null)throw new NullPointerException();/** 進行以下三個步驟處理:** 1. 如果當前運行的線程 , 小于核心線程數 , 那么創建一個新的核心線程 , * 將傳入的任務作為該線程的第一個任務 . * 調用 addWorker 方法 , 會原子性檢查運行狀態和任務數量 ; * 如果在不應該添加線程的情況下執行添加線程操作 , 就會發出錯誤警報 ; * 如果該方法返回 false , 說明當前不能添加線程 , 此時就不要執行添加線程的操作了 ; ** 2. 如果任務被成功放入 線程池任務 隊列 , 不管我們此時是否應該添加線程 , 都需要進行雙重驗證 ;* 雙重驗證 : 添加到任務隊列時驗證一次 , 添加到線程執行時驗證一次 ; * 可能存在這種情況 , 在上次驗證線程運行狀態之后 , 有可能該線程就立刻被銷毀了 ;* 也可能存在進入該方法后 , 線程池被銷毀的情況 ; * 因此我們反復驗證線程狀態 , 如果需要在線程停止時回滾隊列 , 如果沒有線程就創建新線程 ;** 3. 如果不能將任務放入隊列中 , 嘗試創建一個新線程 ; * 如果創建線程失敗 , 說明當前線程池關閉 , 或者線程池中線程飽和 , 此時拒絕執行該任務 ; */int c = ctl.get();if (workerCountOf(c) < corePoolSize) {if (addWorker(command, true))return;c = ctl.get();}/*先調用 isRunning(c) 判斷線程是否在運行中 , 只有運行狀態時 , 線程池才能接收任務 , 先將任務添加到隊列中 , 調用 workQueue.offer(command) 方法實現 , 然后又調用 isRunning(recheck) 判定該線程是否是運行狀態 , 如果不在 , 那么調用 remove(command) 移除該命令 , 然后調用 reject(command) 拒絕執行該命令 , */if (isRunning(c) && workQueue.offer(command)) {int recheck = ctl.get();if (! isRunning(recheck) && remove(command))reject(command);else if (workerCountOf(recheck) == 0)addWorker(null, false);}else if (!addWorker(command, false))reject(command);} }
總結
以上是生活随笔為你收集整理的【Android 异步操作】线程池 ( 线程池 execute 方法源码解析 )的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【Android 异步操作】线程池 (
- 下一篇: 【Android 异步操作】线程池 (