getTask获取任务
//什么情况下会返回null?
//1.rs >= STOP 成立说明:当前的状态最低也是STOP状态,一定要返回null了
//2.前置条件 状态是 SHUTDOWN ,workQueue.isEmpty()
//3.线程池中的线程数量 超过 最大限制时,会有一部分线程返回Null
//4.线程池中的线程数超过corePoolSize时,会有一部分线程 超时后,返回null。
private Runnable getTask() {
//表示当前线程获取任务是否超时 默认false true表示已超时
boolean timedOut = false; // Did the last poll() time out?
//自旋
for (;;) {
//获取最新ctl值保存到c中。
int c = ctl.get();
//获取线程池当前运行状态
int rs = runStateOf(c);
// Check if queue empty only if necessary.
//条件一:rs >= SHUTDOWN 条件成立:说明当前线程池是非RUNNING状态,可能是 SHUTDOWN/STOP....
//条件二:(rs >= STOP || workQueue.isEmpty())
//2.1:rs >= STOP 成立说明:当前的状态最低也是STOP状态,一定要返回null了
//2.2:前置条件 状态是 SHUTDOWN ,workQueue.isEmpty()条件成立:说明当前线程池状态为SHUTDOWN状态 且 任务队列已空,此时一定返回null。
//返回null,runWorker方法就会将返回Null的线程执行线程退出线程池的逻辑。
if (rs >= SHUTDOWN && (rs >= STOP || workQueue.isEmpty())) {
//使用CAS+死循环的方式让 ctl值 -1
decrementWorkerCount();
return null;
}
//执行到这里,有几种情况?
//1.线程池是RUNNING状态
//2.线程池是SHUTDOWN状态 但是队列还未空,此时可以创建线程。
//获取线程池中的线程数量
int wc = workerCountOf(c);
// Are workers subject to culling?
//timed == true 表示当前这个线程 获取 task 时 是支持超时机制的,使用queue.poll(xxx,xxx); 当获取task超时的情况下,下一次自旋就可能返回null了。
//timed == false 表示当前这个线程 获取 task 时 是不支持超时机制的,当前线程会使用 queue.take();
//情况1:allowCoreThreadTimeOut == true 表示核心线程数量内的线程 也可以被回收。
//所有线程 都是使用queue.poll(xxx,xxx) 超时机制这种方式获取task.
//情况2:allowCoreThreadTimeOut == false 表示当前线程池会维护核心数量内的线程。
//wc > corePoolSize
//条件成立:当前线程池中的线程数量是大于核心线程数的,此时让所有路过这里的线程,都是用poll 支持超时的方式去获取任务,
//这样,就会可能有一部分线程获取不到任务,获取不到任务 返回Null,然后..runWorker会执行线程退出逻辑。
boolean timed = allowCoreThreadTimeOut || wc > corePoolSize;
//条件一:(wc > maximumPoolSize || (timed && timedOut))
//1.1:wc > maximumPoolSize 为什么会成立?setMaximumPoolSize()方法,可能外部线程将线程池最大线程数设置为比初始化时的要小
//1.2: (timed && timedOut) 条件成立:前置条件,当前线程使用 poll方式获取task。上一次循环时 使用poll方式获取任务时,超时了
//条件一 为true 表示 线程可以被回收,达到回收标准,当确实需要回收时再回收。
//条件二:(wc > 1 || workQueue.isEmpty())
//2.1: wc > 1 条件成立,说明当前线程池中还有其他线程,当前线程可以直接回收,返回null
//2.2: workQueue.isEmpty() 前置条件 wc == 1, 条件成立:说明当前任务队列 已经空了,最后一个线程,也可以放心的退出。
if ((wc > maximumPoolSize || (timed && timedOut))
&& (wc > 1 || workQueue.isEmpty())) {
//使用CAS机制 将 ctl值 -1 ,减1成功的线程,返回null
//CAS成功的,返回Null
//CAS失败? 为什么会CAS失败?
//1.其它线程先你一步退出了
//2.线程池状态发生变化了。
if (compareAndDecrementWorkerCount(c))
return null;
//再次自旋时,timed有可能就是false了,因为当前线程cas失败,很有可能是因为其它线程成功退出导致的,再次咨询时
//检查发现,当前线程 就可能属于 不需要回收范围内了。
continue;
}
try {
//获取任务的逻辑
Runnable r = timed ?
workQueue.poll(keepAliveTime, TimeUnit.NANOSECONDS) :
workQueue.take();
//条件成立:返回任务
if (r != null)
return r;
//说明当前线程超时了...
timedOut = true;
} catch (InterruptedException retry) {
timedOut = false;
}
}
}
private void processWorkerExit(Worker w, boolean completedAbruptly) {
//条件成立:代表当前w 这个worker是发生异常退出的,task任务执行过程中向上抛出异常了..
//异常退出时,ctl计数,并没有-1
if (completedAbruptly) // If abrupt, then workerCount wasn't adjusted
decrementWorkerCount();
//获取线程池的全局锁引用
final ReentrantLock mainLock = this.mainLock;
//加锁
mainLock.lock();
try {
//将当前worker完成的task数量,汇总到线程池的completedTaskCount
completedTaskCount += w.completedTasks;
//将worker从池子中移除..
workers.remove(w);
} finally {
//释放全局锁
mainLock.unlock();
}
tryTerminate();
//获取最新ctl值
int c = ctl.get();
//条件成立:当前线程池状态为 RUNNING 或者 SHUTDOWN状态
if (runStateLessThan(c, STOP)) {
//条件成立:当前线程是正常退出..
if (!completedAbruptly) {
//min表示线程池最低持有的线程数量
//allowCoreThreadTimeOut == true => 说明核心线程数内的线程,也会超时被回收。 min == 0
//allowCoreThreadTimeOut == false => min == corePoolSize
int min = allowCoreThreadTimeOut ? 0 : corePoolSize;
//线程池状态:RUNNING SHUTDOWN
//条件一:假设min == 0 成立
//条件二:! workQueue.isEmpty() 说明任务队列中还有任务,最起码要留一个线程。
if (min == 0 && ! workQueue.isEmpty())
min = 1;
//条件成立:线程池中还拥有足够的线程。
//考虑一个问题: workerCountOf(c) >= min => (0 >= 0) ?
//有可能!
//什么情况下? 当线程池中的核心线程数是可以被回收的情况下,会出现这种情况,这种情况下,当前线程池中的线程数 会变为0
//下次再提交任务时,会再创建线程。
if (workerCountOf(c) >= min)
return; // replacement not needed
}
//1.当前线程在执行task时 发生异常,这里一定要创建一个新worker顶上去。
//2.!workQueue.isEmpty() 说明任务队列中还有任务,最起码要留一个线程。 当前状态为 RUNNING || SHUTDOWN
//3.当前线程数量 < corePoolSize值,此时会创建线程,维护线程池数量在corePoolSize个。
addWorker(null, false);
}
}
线程池关闭
shutdown
public void shutdown() {
final ReentrantLock mainLock = this.mainLock;
//获取线程池全局锁
mainLock.lock();
try {
checkShutdownAccess();
//设置线程池状态为SHUTDOWN
advanceRunState(SHUTDOWN);
//中断空闲线程
interruptIdleWorkers();
//空方法,子类可以扩展
onShutdown(); // hook for ScheduledThreadPoolExecutor
} finally {
//释放线程池全局锁
mainLock.unlock();
}
tryTerminate();
}
private void interruptIdleWorkers() {
interruptIdleWorkers(false);
}
//onlyOne == true 说明只中断一个线程 ,false 则中断所有线程
//共同前提,worker是空闲状态。
private void interruptIdleWorkers(boolean onlyOne) {
final ReentrantLock mainLock = this.mainLock;
//持有全局锁
mainLock.lock();
try {
//迭代所有worker
for (Worker w : workers) {
//获取当前worker的线程 保存到t
Thread t = w.thread;
//条件一:条件成立:!t.isInterrupted() == true 说明当前迭代的这个线程尚未中断。
//条件二:w.tryLock() 条件成立:说明当前worker处于空闲状态,可以去给它一个中断信号。 目前worker内的线程 在 queue.take() | queue.poll()
//阻塞中。因为worker执行task时,是加锁的!
if (!t.isInterrupted() && w.tryLock()) {
try {
//给当前线程中断信号..处于queue阻塞的线程,会被唤醒,唤醒后,进入下一次自旋时,可能会return null。执行退出相关的逻辑。
t.interrupt();
} catch (SecurityException ignore) {
} finally {
//释放worker的独占锁。
w.unlock();
}
}
if (onlyOne)
break;
}
} finally {
//释放全局锁。
mainLock.unlock();
}
}
shutdownNow
public List<Runnable> shutdownNow() {
//返回值引用
List<Runnable> tasks;
final ReentrantLock mainLock = this.mainLock;
//获取线程池全局锁
mainLock.lock();
try {
checkShutdownAccess();
//设置线程池状态为STOP
advanceRunState(STOP);
//中断线程池中所有线程
interruptWorkers();
//导出未处理的task
tasks = drainQueue();
} finally {
mainLock.unlock();
}
tryTerminate();
//返回当前任务队列中 未处理的任务。
return tasks;
}
private void interruptWorkers() {
final ReentrantLock mainLock = this.mainLock;
//获取线程池全局锁
mainLock.lock();
try {
//遍历所有worker
for (Worker w : workers)
//interruptIfStarted() 如果worker内的thread 是启动状态,则给它一个中断信号。。
w.interruptIfStarted();
} finally {
//释放线程池全局锁
mainLock.unlock();
}
}
设置线程池状态 (转化)
final void tryTerminate() {
//自旋
for (;;) {
//获取最新ctl值
int c = ctl.get();
//条件一:isRunning(c) 成立,直接返回就行,线程池很正常!
//条件二:runStateAtLeast(c, TIDYING) 说明 已经有其它线程 在执行 TIDYING -> TERMINATED状态了,当前线程直接回去。
//条件三:(runStateOf(c) == SHUTDOWN && ! workQueue.isEmpty())
//SHUTDOWN特殊情况,如果是这种情况,直接回去。得等队列中的任务处理完毕后,再转化状态。
if (isRunning(c) ||
runStateAtLeast(c, TIDYING) ||
(runStateOf(c) == SHUTDOWN && ! workQueue.isEmpty()))
return;
//条件成立:当前线程池中的线程数量 > 0
if (workerCountOf(c) != 0) { // Eligible to terminate
// 中断空闲线程 其实就是通过中断信号 唤醒阻塞的线程
interruptIdleWorkers(ONLY_ONE);
return;
}
final ReentrantLock mainLock = this.mainLock;
//获取线程池全局锁
mainLock.lock();
try {
//设置线程池状态为TIDYING状态。
if (ctl.compareAndSet(c, ctlOf(TIDYING, 0))) {
try {
//调用钩子方法
terminated();
} finally {
//设置线程池状态为TERMINATED状态。
ctl.set(ctlOf(TERMINATED, 0));
//唤醒调用 awaitTermination() 方法的线程。
termination.signalAll();
}
return;
}
} finally {
//释放线程池全局锁。
mainLock.unlock();
}
// else retry on failed CAS
}
}