keepAliveTime参数
如果线程池当前拥有的线程数超过corePoolSize线程数, 并且空闲的线程闲置时间超过了keepAliveTime,这些空闲线程会被终止。 这提供了一种 当线程池变得不活跃时减少资源消耗的方法。如果池变得更活跃,新线程将被构建。此参数也可以是使用setKeepAliveTime(long, TimeUnit)。默认情况下,仅当线程数超过核心线程数时上面策略才生效。但 方法allowCoreThreadTimeOut(boolean)可将此超时策略也应用于核心线程。
实现原理
runWorker
Worker实现了Runnable接口,run方法里面调用runWorker(this)来实现work的业务逻辑。
final void runWorker(Worker w) {
Thread wt = Thread.currentThread();
Runnable task = w.firstTask;
w.firstTask = null;
w.unlock(); // allow interrupts
boolean completedAbruptly = true;
try {
while (task != null || (task = getTask()) != null) {
w.lock();
// If pool is stopping, ensure thread is interrupted;
// if not, ensure thread is not interrupted. This
// requires a recheck in second case to deal with
// shutdownNow race while clearing interrupt
if ((runStateAtLeast(ctl.get(), STOP) ||
(Thread.interrupted() &&
runStateAtLeast(ctl.get(), STOP))) &&
!wt.isInterrupted())
wt.interrupt();
try {
beforeExecute(wt, task);
Throwable thrown = null;
try {
task.run();
} catch (RuntimeException x) {
thrown = x; throw x;
} catch (Error x) {
thrown = x; throw x;
} catch (Throwable x) {
thrown = x; throw new Error(x);
} finally {
afterExecute(task, thrown);
}
} finally {
task = null;
w.completedTasks++;
w.unlock();
}
}
completedAbruptly = false;
} finally {
processWorkerExit(w, completedAbruptly);
}
}
runWorker方法的实现里面,如果getTask方法获取不到任务,就会进入processWorkerExit方法,把work终止。
getTask
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?
boolean timed = allowCoreThreadTimeOut || wc > corePoolSize;
if ((wc > maximumPoolSize || (timed && timedOut))
&& (wc > 1 || workQueue.isEmpty())) {
if (compareAndDecrementWorkerCount(c))
return null;
continue;
}
try {
Runnable r = timed ?
workQueue.poll(keepAliveTime, TimeUnit.NANOSECONDS) :
workQueue.take();
if (r != null)
return r;
timedOut = true;
} catch (InterruptedException retry) {
timedOut = false;
}
}
}
如果允许核心线程数超时空闲移除 或者 工作线程数超过核心线程数,则通过poll方法从阻塞队列里面获取任务,否则通过take阻塞获取任务。
队列操作描述
- poll:等待指定的等待时间,检索并删除阻塞队列的头部元素。
- take:等待直到元素可用,检索并删除阻塞队列的头部元素。
当poll方法超时之后,会设置timedOut为true。再次循环时如果工作线程数大于1,或者工作队列为空,就调用compareAndDecrementWorkerCount减少工作线程数,如果成功则返回null。
当getTask返回null时,在processWorkerExit方法里面对应的work线程就会被移除。