/**
* Initiates an orderly shutdown in which previously submitted
* tasks are executed, but no new tasks will be accepted.
* Invocation has no additional effect if already shut down.
* 执行一个顺序的shutdown操作,在此之前已提交的任务将会被执行,但不再接受新任务。
* 如果线程池已经shutdown,调用此方法不会产生副作用。
* <p>This method does not wait for previously submitted tasks to
* complete execution. Use {@link #awaitTermination awaitTermination}
* to do that.
* 此方法不会等待已提交的任务执行完成,需使用awaitTermination 来达到此目的
* @throws SecurityException {@inheritDoc}
*/
public void shutdown() {
//首先获得线程池的可重入锁
final ReentrantLock mainLock = this.mainLock;
mainLock.lock();
try {
//检查shutdown的权限
checkShutdownAccess();
advanceRunState(SHUTDOWN);
interruptIdleWorkers();
//ScheduledThreadPoolExecutor的钩子函数
onShutdown(); // hook for ScheduledThreadPoolExecutor
} finally {
mainLock.unlock();
}
tryTerminate();
}
/**
* If there is a security manager, makes sure caller has
* permission to shut down threads in general (see shutdownPerm).
* 如果存在安全管理器,请确保调用者有在一般情况下关闭线程的权限。
* If this passes, additionally makes sure the caller is allowed
* to interrupt each worker thread. This might not be true even if
* first check passed, if the SecurityManager treats some threads
* specially.
* 如果这一条通过,还要确保调用者被允许中断每个工作线程。
* 即使第一条过了,如果安全管理器对某些线程特殊处理,仍可能导致检查不通过。
*/
private void checkShutdownAccess() {
SecurityManager security = System.getSecurityManager();
if (security != null) {
security.checkPermission(shutdownPerm);
final ReentrantLock mainLock = this.mainLock;
mainLock.lock();
try {
for (Worker w : workers)
security.checkAccess(w.thread);
} finally {
mainLock.unlock();
}
}
}
/**
* Transitions runState to given target, or leaves it alone if
* already at least the given target.
* 将线程池的运行状态置为指定的状态(即SHUTDOWN = 0 << COUNT_BITS),如果已经>=SHUTDOWN,就无需处理了
* @param targetState the desired state, either SHUTDOWN or STOP
* (but not TIDYING or TERMINATED -- use tryTerminate for that)
*/
private void advanceRunState(int targetState) {
for (;;) {
//无限循环,只有满足已至少是SHUTDOWN,或者cas把状态变为SHUTDOWN成功才退出
int c = ctl.get();
//这里还一起把当前工作者数量也cas设置了,因为ctl的低29位是存储worker的计数的
if (runStateAtLeast(c, targetState) ||
ctl.compareAndSet(c, ctlOf(targetState, workerCountOf(c))))
break;
}
}
/**
* Common form of interruptIdleWorkers, to avoid having to
* remember what the boolean argument means.
* interruptIdleWorkers的一般形式,避免需要记忆boolean 参数的意义
*/
private void interruptIdleWorkers() {
interruptIdleWorkers(false);
}
private void interruptIdleWorkers(boolean onlyOne) {
final ReentrantLock mainLock = this.mainLock;
mainLock.lock();
try {
for (Worker w : workers) {
Thread t = w.thread;
//当当前worker的线程t未被中断且空闲时才去尝试设置中断标志,其中w.tryLock()返回true表示拿到的worker w的独占锁,
//说明此worker并非在执行,也就达到了不去中断正在执行线程的效果
if (!t.isInterrupted() && w.tryLock()) {
try {
t.interrupt();
} catch (SecurityException ignore) {
} finally {
w.unlock();
}
}
if (onlyOne)
break;
}
} finally {
mainLock.unlock();
}
}
private final class Worker
extends AbstractQueuedSynchronizer
implements Runnable
{
public boolean tryLock() { return tryAcquire(1); }
protected boolean tryAcquire(int unused) {
//AQS里面的cas操作
if (compareAndSetState(0, 1)) {
setExclusiveOwnerThread(Thread.currentThread());
return true;
}
return false;
}
}
shutdown与shutdownNow很重要的区别就是shutdown只设置空闲线程的中断标志位,实现这个功能的前提是需要获得worker的独占锁,只有在worker不是在执行线程任务时,此独占锁才有可能被获得。