概述
这里聊几个ThreadPoolExecutor涉及到的两个关键的方法。
1. void shutdown()
2. List shutdownNow()
shutdown()
执行线程池的关闭操作,此时不会接收新的任务,但是会执行完任务队列的任务。
public void shutdown() {
final ReentrantLock mainLock = this.mainLock;
mainLock.lock();
try {
checkShutdownAccess();// 校验权限,不重要
advanceRunState(SHUTDOWN);// CAS设置线程池状态为SHUTDOWN
interruptIdleWorkers();//中断空闲线程
onShutdown(); // hook for ScheduledThreadPoolExecutor
} finally {
mainLock.unlock();
}
tryTerminate();
}
中断空闲线程
private void interruptIdleWorkers(boolean onlyOne) {
final ReentrantLock mainLock = this.mainLock;
mainLock.lock();
try {
for (Worker w : workers) {
Thread t = w.thread;
if (!t.isInterrupted() && w.tryLock()) {// 判断是否是空闲线程。w.tryLock()如果拿不到锁,说明线程正在执行,因为runWorker方法执行run的时候要先w.lock获得锁,这时候这里是获取不到锁的。
try {
t.interrupt();// 执行线程中断,runWorker中while循环中等待从队列获取的线程会退出来,completedAbruptly = false;执行processWorkerExit(w, completedAbruptly)。
} catch (SecurityException ignore) {
} finally {
w.unlock();
}
}
if (onlyOne)
break;
}
} finally {
mainLock.unlock();
}
}
中止线程池里的所有线程
final void tryTerminate() {
for (;;) {
int c = ctl.get();
if (isRunning(c) ||
runStateAtLeast(c, TIDYING) ||
(runStateOf(c) == SHUTDOWN && ! workQueue.isEmpty()))
return;// 如果线程池处于running或任务队列不为空,不做操作
if (workerCountOf(c) != 0) { // 如果有线程在执行任务
interruptIdleWorkers(ONLY_ONE);// 只中断一个线程。下面的操作交给其他线程执行。这里保证只有一个线程往下面走。
return;
}
final ReentrantLock mainLock = this.mainLock;
mainLock.lock();
try {
if (ctl.compareAndSet(c, ctlOf(TIDYING, 0))) {
try {
terminated();// 执行中断的钩子方法
} finally {
ctl.set(ctlOf(TERMINATED, 0));// 设置线程池状态为中止
termination.signalAll();// 唤醒等待在condition上的所有线程
}
return;
}
} finally {
mainLock.unlock();
}
// else retry on failed CAS
}
}
等待线程池线程中断完毕
public boolean awaitTermination(long timeout, TimeUnit unit)
throws InterruptedException {
long nanos = unit.toNanos(timeout);
final ReentrantLock mainLock = this.mainLock;
mainLock.lock();
try {
for (;;) {
if (runStateAtLeast(ctl.get(), TERMINATED))
return true;
if (nanos <= 0)
return false;
nanos = termination.awaitNanos(nanos);
}
} finally {
mainLock.unlock();
}
}
shutdownNow()
public List<Runnable> shutdownNow() {
List<Runnable> tasks;
final ReentrantLock mainLock = this.mainLock;
mainLock.lock();
try {
checkShutdownAccess();
advanceRunState(STOP);// 设置线程池状态为stop
interruptWorkers();//中止所有线程
tasks = drainQueue();//将workQueue的所有未执行任务拷贝给List tasks返回
} finally {
mainLock.unlock();
}
tryTerminate();// 尝试中止线程
return tasks;// 返回未执行的任务
}
总结
线程池怎么保证内部一定有一定数量的线程在运行?
注:由于线程池逻辑复杂,我们只是分析最普遍的逻辑。
拿ThreadPoolExecutor举例子!
重点方法在runWorker(Worker w)
方法的while (task != null || (task = getTask()) != null)
这个while循环内。
- 如果是正常通过execute(runnable)进来的
task != null
成立,执行task.run()
方法,结束后回到while (task != null || (task = getTask()) != null)
,此时task==null
,方法阻塞在(task = getTask()) != null
,从阻塞队列拿任务 (task = getTask()) != null
方法支持超时机制获取队列任务。如果当前正在执行的任务数或者核心线程允许超时,boolean timed = allowCoreThreadTimeOut || wc > corePoolSize
为true,否则为false- 接着从队列获取任务
Runnable r = timed ? workQueue.poll(keepAliveTime, TimeUnit.NANOSECONDS) : workQueue.take();
,如果拿到了,就返回任务r,否则返回null,阻塞方法从while (task != null || (task = getTask()) != null)
返回 - 当
(task = getTask()) != null
成立,执行任务的run方法,正常结束后接着阻塞在while (task != null || (task = getTask()) != null)
- 当
(task = getTask()) != null
不成立,退出while (task != null || (task = getTask()) != null)
循环,此时completedAbruptly = false;
和w == null
,执行processWorkerExit(w, completedAbruptly)
方法 - 进入
processWorkerExit(w, completedAbruptly)
方法后,执行tryTerminate()
方法,由于isRunning(c)
为true,直接返回,线程从tryTerminate()
方法返回,继续往下执行 if (runStateLessThan(c, STOP))
和if (!completedAbruptly)
同时成立,如果当前正在执行的任务数量大于等于允许的最小线程数量,即if (workerCountOf(c) >= min)
成立,线程从processWorkerExit(w, completedAbruptly)
退出,线程死亡。如果当前正在执行的任务数量小于允许的最小线程数量,即if (workerCountOf(c) >= min)
不成立,执行addWorker(null, false)
方法,使用线程工厂重新创建一个线程,重新进入runWorker(Worker w)
方法,阻塞在while (task != null || (task = getTask()) != null)
,重复步骤1。