try {
Runnabler = timed ?
workQueue.poll(keepAliveTime,TimeUnit.NANOSECONDS) :
workQueue.take();
if(r != null)
returnr;
timedOut= true;
} catch (InterruptedException retry) {
timedOut= false;
}
继续走起,catch之后,timedOut = false,然后又回到①for循环中,再次判断线程池的状态②,前面走到interruptIdleWorkers时,线程池已是SHUTDOWN了,所以进入return null 分支,return null 之后重新回到runWorker,退出while循环,又进入到processWorkerExit方法了,然后继续tryTerminate –> interruptIdleWorkers…一个个地将闲置的线程回收,直至回收完成,线程池terminated。
for (;;) { //①
intc = ctl.get();
intrs = runStateOf(c);
//Check if queue empty only if necessary.
if(rs >= SHUTDOWN && (rs >= STOP || workQueue.isEmpty())) { //②
decrementWorkerCount();
returnnull;
}
整个线程池执行任务的流程就如上所述了。
接下来再来看看线程池的关闭:shutdown、shutdownNow。有了上面的基础这两个方法就很好理解了:
shutdown
checkShutdownAccess(); //检查关闭线程池的权限
advanceRunState(SHUTDOWN); //把线程池状态更新到SHUTDOWN
interruptIdleWorkers(); //中断闲置的Worker
onShutdown(); //钩子方法,默认不处理。ScheduledThreadPoolExecutor会做一些处理
tryTerminate(); // 尝试结束线程池,上面已经分析过了
// shutdownNow方法会有返回值的,返回的是一个任务列表,而shutdown方法没有返回值
public List shutdownNow() {
List tasks;
final ReentrantLock mainLock = this.mainLock;
mainLock.lock(); // shutdownNow操作也需要加锁,防止并发
try {
checkShutdownAccess(); //检查关闭线程池的权限
advanceRunState(STOP); //把线程池状态更新到STOP
interruptWorkers(); //中断Worker的运行
tasks = drainQueue();
}finally {
mainLock.unlock(); //解锁
}
tryTerminate(); //尝试结束线程池,上面已经分析过了
return tasks;
}
shutdownNow的中断和shutdown方法不一样,调用的是interruptWorkers方法:
然后这个方法调用的是interruptIfStarted
void interruptIfStarted() {
Thread t;
//Worker无论是否被持有锁,只要还没被中断,那就中断Worker
if(getState() >= 0 && (t = thread) != null &&!t.isInterrupted()) {
try {
t.interrupt(); //强行中断Worker的执行
} catch (SecurityException ignore) {
}
}
}
shutdown方法会更新状态到SHUTDOWN,不会影响阻塞队列里任务的执行,但是不会执行新进来的任务。同时也会回收闲置的Worker,直到任务全部执行完。
shutdownNow方法会更新状态到STOP,会影响阻塞队列的任务执行,也不会执行新进来的任务。同时会回收所有的Worker。
http://fangjian0423.github.io/2016/03/22/java-threadpool-analysis/
http://www.cnblogs.com/zhanjindong/p/java-concurrent-package-ThreadPoolExecutor.html