java執行緒池(ThreadPoolExecutor)原始碼解析四
阿新 • • 發佈:2019-01-29
getTask()方法
/*
* 依賴當前的配置阻塞或等待指定時間獲取一個任務,如果在發生以下情況那麼
* 當前的worker必須退出,則返回null
* 1. 當前執行緒數超過了最大執行緒數(可能由於動態修改了最大執行緒數)
* 2. 執行緒池狀態未STOP
* 3. 執行緒池狀態為SHUTDOWN 並且任務佇列未空
* 4. 當前執行緒等待獲取任務超時,並且要釋放(比如設定了核心執行緒數可以超時或者執行緒數>核心執行緒數)
*
* @return 返回下一個任務,如果當前worker必須退出,返回null,並對執行緒數-1
*/
private Runnable getTask () {
boolean timedOut = false; // 上一次poll方法是否超時了
retry:
for (;;) {
int c = ctl.get();
int rs = runStateOf(c);
if (rs >= SHUTDOWN && (rs >= STOP || workQueue.isEmpty())) {
decrementWorkerCount();
return null;
}
boolean timed; // 標示當前執行緒超時是否退出
for (;;) {
int wc = workerCountOf(c);
//如果設定了核心執行緒可以超時或者執行緒數>核心執行緒數,那麼當前執行緒如果回去任務超時了,則退出
timed = allowCoreThreadTimeOut || wc > corePoolSize;
//如果工作執行緒數小於最大執行緒數並且當前執行緒超時不是超時退出或上一次沒有超時,跳出迴圈,繼續後面獲取任務
if (wc <= maximumPoolSize && ! (timedOut && timed))
break ;
//如果工作執行緒數>最大執行緒數,或者當前執行緒超時要退出,並且上一次已經超時了,
//CAS 工作執行緒數-1,workerCount-1成功返回空,否則重試
if (compareAndDecrementWorkerCount(c))
return null;
//如果執行狀態變化了,從外層迴圈重新校驗執行緒池狀態
//否則直接執行內層迴圈
c = ctl.get(); // Re-read ctl
if (runStateOf(c) != rs)
continue retry;
}
try {
Runnable r = timed ?
workQueue.poll(keepAliveTime, TimeUnit.NANOSECONDS) :
workQueue.take();
if (r != null)
return r;
timedOut = true;//取任務超時
} catch (InterruptedException retry) {
timedOut = false;
}
}
}