/**
* Executes the given task sometime in the future. The task
* may execute in a new thread or in an existing pooled thread.
* 在未來某個時間執行指定傳入的任務。
* 任務可以在一個新線程中執行,也可能在線程池中已存在的一個線程中執行。
* If the task cannot be submitted for execution, either because this
* executor has been shutdown or because its capacity has been reached,
* the task is handled by the current {@code RejectedExecutionHandler}.
* 如果這個任務不能被提交執行,或者是因爲這個executor已經被shutdown,又或者因爲已經觸及線程池的最大容量,
* 這個任務被當前的拒絕策略RejectedExecutionHandler處理掉了
* @param command the task to execute
* @throws RejectedExecutionException at discretion of
* {@code RejectedExecutionHandler}, if the task
* cannot be accepted for execution
* @throws NullPointerException if {@code command} is null
*/
public void execute(Runnable command) {
if (command == null)
throw new NullPointerException();
/*
* Proceed in 3 steps:
*
* 1. If fewer than corePoolSize threads are running, try to
* start a new thread with the given command as its first
* task. The call to addWorker atomically checks runState and
* workerCount, and so prevents false alarms that would add
* threads when it shouldn't, by returning false.
* 如果線程池當前正在運行的線程數小於corePoolSize,將嘗試新起一個線程,傳入的Runnable command將作爲它的第一個任務。
* 調用addWorker將原子性的檢查runState線程池運行狀態和workerCount工作者數量,並且當不應該新增線程時通過return false來阻止。
* 2. If a task can be successfully queued, then we still need
* to double-check whether we should have added a thread
* (because existing ones died since last checking) or that
* the pool shut down since entry into this method. So we
* recheck state and if necessary roll back the enqueuing if
* stopped, or start a new thread if there are none.
* 如果一個任務能夠成功的加入隊列,這時我們仍然需要再次檢查我們是否應該新起一個線程(因爲從上次檢查之後已存在的線程有可能消亡了)
* 或者進入此方法後線程池shutdown了。
* 所以我們還是要重新檢查線程池狀態,以及當線程池停止是否有必要將入隊列的操作回滾,
* 或者線程池中沒有線程時需要新起一個線程
* 3. If we cannot queue task, then we try to add a new
* thread. If it fails, we know we are shut down or saturated
* and so reject the task.
* 如果不能將任務入隊列,這時我們嘗試新起一個線程,如果新起線程失敗,我們就知道線程池已經被shutdown或者線程池飽和了,
* 這時就需要拒絕任務了
*/
int c = ctl.get();
//如果worker的數量小於corePoolSize
if (workerCountOf(c) < corePoolSize) {
//如果添加任務成功就可以返回了
if (addWorker(command, true))
return;
c = ctl.get();
}
//如果workerCount不小於核心線程數,那麼接下來嘗試放到blockingqueue了
//ctl<SHUTDOWN且入隊列成功
if (isRunning(c) && workQueue.offer(command)) {
//二次檢查ctl
int recheck = ctl.get();
//ctl>=SHUTDOWN且移除任務成功
if (! isRunning(recheck) && remove(command))
//拒絕任務
reject(command);
//如果workerCount==0,這時候創建空的worker,使用maximumPoolSize
else if (workerCountOf(recheck) == 0)
addWorker(null, false);
}
//接下來是嘗試添加超過corePoolSize,<=maximumPoolSize,如果添加失敗則採用拒絕策略
else if (!addWorker(command, false))
reject(command);
}
private boolean addWorker(Runnable firstTask, boolean core) {
retry:
for (;;) {
//得到ctl
int c = ctl.get();
//c & ~CAPACITY 只保留高3位狀態位1
int rs = runStateOf(c);
// Check if queue empty only if necessary.
//3種情況,1、線程池>SHUTDOWN
// 2、線程池狀態==SHUTDOWN 且firstTask != null
// 3、線程池狀態==SHUTDOWN 且firstTask == null且workQueue.isEmpty()
//當firstTask爲空時是爲了創建一個沒有任務的線程,再從workQueue中獲取任務,如果workQueue已經爲空,那麼就沒有添加新worker的必要了
if (rs >= SHUTDOWN &&
! (rs == SHUTDOWN &&
firstTask == null &&
! workQueue.isEmpty()))
return false;
for (;;) {
//workCount
int wc = workerCountOf(c);
//如果workCount>=最大線程數容量或者>=core
//core是傳進來的參數,true代表使用corePoolSize計量,false代表使用maximumPoolSize
if (wc >= CAPACITY ||
wc >= (core ? corePoolSize : maximumPoolSize))
return false;
//如果cas操作將WorkerCount+1成功,直接break外層循環,繼續往下走
if (compareAndIncrementWorkerCount(c))
break retry;
//重新get ctl
c = ctl.get(); // Re-read ctl
//如果runstate變了就要重新從外層循環開始判斷
if (runStateOf(c) != rs)
continue retry;
//否則走到這裏只能是因爲workerCount變了導致cas失敗,這時重新開始內層循環
// else CAS failed due to workerCount change; retry inner loop
}
}
boolean workerStarted = false;
boolean workerAdded = false;
Worker w = null;
try {
//new一個worker
w = new Worker(firstTask);
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());
//若線程池狀態<SHUTDOWN或
// ==SHUTDOWN且是一個空任務
if (rs < SHUTDOWN ||
(rs == SHUTDOWN && firstTask == null)) {
//如果線程已經啓動,拋異常
if (t.isAlive()) // precheck that t is startable
throw new IllegalThreadStateException();
//把new worker添加到worker set中
workers.add(w);
int s = workers.size();
//largestPoolSize用來記錄線程池線程數曾達到的最大值
if (s > largestPoolSize)
largestPoolSize = s;
//標記worker已添加
workerAdded = true;
}
} finally {
mainLock.unlock();
}
//標記worker已添加到worker set中,啓動線程標記爲已啓動
if (workerAdded) {
t.start();
workerStarted = true;
}
}
} finally {
//如果worker未啓動,進行添加worker失敗的後續處理
if (! workerStarted)
addWorkerFailed(w);
}
return workerStarted;
}
/**
* Rolls back the worker thread creation.
* 回滾創建worker線程的操作
* - removes worker from workers, if present
* 從worker set移除此worker
* - decrements worker count
* worker count遞減
* - rechecks for termination, in case the existence of this
* worker was holding up termination
* 重新檢查是否要terminate,防止是由於這個回退worker hold住了線程池使其不能停止
*/
private void addWorkerFailed(Worker w) {
final ReentrantLock mainLock = this.mainLock;
mainLock.lock();
try {
if (w != null)
workers.remove(w);
//循環嘗試,直到cas成功,完成計數-1
decrementWorkerCount();
//嘗試停止線程池
tryTerminate();
} finally {
mainLock.unlock();
}
}
/**
* Transitions to TERMINATED state if either (SHUTDOWN and pool
* and queue empty) or (STOP and pool empty). If otherwise
* 如果線程池處於SHUTDOWN狀態且線程池及隊列都爲空,或者STOP且線程池爲空,轉換成TERMINATED狀態
* eligible to terminate but workerCount is nonzero, interrupts an
* idle worker to ensure that shutdown signals propagate. This
* 如果符合terminate的條件但workerCount不爲0,則中斷一個空閒worker以保證這個shutdown信號被傳遞
* method must be called following any action that might make
* termination possible -- reducing worker count or removing tasks
* 此方法應該在任何可能導致線程池終止的操作之後被調用,這些操作可能是worker數量被減少或者在shutdown的時候從線程隊列移除了任務
* from the queue during shutdown. The method is non-private to
* allow access from ScheduledThreadPoolExecutor.
* 此方法不是私有的,爲了能夠讓ScheduledThreadPoolExecutor訪問到
*/
final void tryTerminate() {
for (;;) {
int c = ctl.get();
//c < SHUTDOWN還處於運行狀態
//或者已經是TIDYING或者TERMINATED狀態了,就無需再tryTerminate
//或者狀態是SHUTDOWN但工作隊列不爲空,這時候也不能tryTerminate
if (isRunning(c) ||
runStateAtLeast(c, TIDYING) ||
(runStateOf(c) == SHUTDOWN && ! workQueue.isEmpty()))
return;
//如果能再往下走,說明處於SHUTDOWN狀態且workQueue是空的
//如果worker數量不爲0,這時候去中斷一個空閒的worker,即用中斷去喚醒一個阻塞在從workqueue獲取任務的core線程,且只中斷一個
if (workerCountOf(c) != 0) { // Eligible to terminate
interruptIdleWorkers(ONLY_ONE);
return;
}
final ReentrantLock mainLock = this.mainLock;
mainLock.lock();
try {
//cas將線程池狀態變爲TIDYING,workercount變爲0
if (ctl.compareAndSet(c, ctlOf(TIDYING, 0))) {
try {
//如果cas成功了就調用terminated,這裏應該可以看成是一個鉤子方法,本身是個空方法,由子類去override
terminated();
} finally {
//最後把ctl設置成TERMINATED,workercount爲0
ctl.set(ctlOf(TERMINATED, 0));
//喚醒那些調用了awaitTermination()等待線程池終止的線程
termination.signalAll();
}
return;
}
} finally {
mainLock.unlock();
}
// else retry on failed CAS
}
}