刷题刷出新高度,偷偷领先!偷偷领先!偷偷领先! 关注我们,悄悄成为最优秀的自己!
ThreadPoolExecutor 中线程执行getTask()返回null,就会被回收。
我们来看看getTask方法是怎么处理的:
/**
* Performs blocking or timed wait for a task, depending on
* current configuration settings, or returns null if this worker
* must exit because of any of:
* 1. There are more than maximumPoolSize workers (due to
* a call to setMaximumPoolSize).
* 2. The pool is stopped.
* 3. The pool is shutdown and the queue is empty.
* 4. This worker timed out waiting for a task, and timed-out
* workers are subject to termination (that is,
* {@code allowCoreThreadTimeOut || workerCount > corePoolSize})
* both before and after the timed wait, and if the queue is
* non-empty, this worker is not the last thread in the pool.
*
* @return task, or null if the worker must exit, in which case
* workerCount is decremented
*/
private Runnable getTask() {
boolean timedOut = false; // Did the last poll() time out?
for (;;) {
int c = ctl.get();
int rs = runStateOf(c);
// Check if queue empty only if necessary.
if (rs >= SHUTDOWN && (rs >= STOP || workQueue.isEmpty())) {
decrementWorkerCount();
return null;
}
int wc = workerCountOf(c);
// Are workers subject to culling? // timed = true 表示存在非核心线程
boolean timed = allowCoreThreadTimeOut || wc > corePoolSize;
// 这个if条件成立的前提:必须存在非核心线程
if ((wc > maximumPoolSize || (timed && timedOut))
&& (wc > 1 || workQueue.isEmpty())) {
if (compareAndDecrementWorkerCount(c))
return null; // 这个null就是非核心线程被销毁的原因
continue;
}
try {
Runnable r = timed ?
workQueue.poll(keepAliveTime, TimeUnit.NANOSECONDS) :
workQueue.take();
if (r != null)
return r; // 能取到任务就返回,否则设置timedOut进去死循环
timedOut = true;
} catch (InterruptedException retry) {
timedOut = false;
}
}
}
通过上面代码分析,可以得出结论:
你如果设置了keepAliveTime并且设置executor.allowCoreThreadTimeOut(false),当线程池的数量超过corePoolSize时,超过的部分,多余即空闲的线程的存活时间超过keepAliveTime就会被回收。
回收分两种场景:
1、未调用shutdown() ,RUNNING状态下全部任务执行完成的场景
线程数量大于corePoolSize,线程超时阻塞,超时唤醒后CAS减少工作线程数,如果CAS成功,返回null,线程回收。否则进入下一次循环。当工作者线程数量小于等于corePoolSize,就可以一直阻塞了。
2、调用shutdown() ,全部任务执行完成的场景
shutdown() 会向所有线程发出中断信号,这时有两种可能:
所谓的核心线程与非核心线程,在线程池的数据结构中并没有明确区分,只要线程池剩余的线程数小于等于corePoolSize,那么剩下的线程都可以称为核心线程;
设置是否回收在保活时间后依然没没有任务执行核心线程
executor.allowCoreThreadTimeOut(true) 该属性缺省值为false
本文链接:线程池中线程回收是如何处理的 ?
版权声明:本站点所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明文章出处。让学习像火箭一样快速,微信扫码,获取考试解析、体验刷题服务,开启你的学习加速器!
