线程池的难点和重点
让我们一起来看看线程池是如何回收和维持运作线程的核心技术体系。
线程池的前提和介绍
一般来讲 JDK 线程池就是 ThreadPoolExecutor,大多数会对线程池执行任务的流程有了大体了解,实际上这个流程也十分通俗易懂,就不再赘述了,我之前的文章也介绍过了相关的技术点分析和介绍说明。
讲一讲线程池是如何回收线程的?
runWorker(Worker w)
复制代码
线程执行的基本流程
-
工作线程启动后,就进入 runWorker(Worker w) 方法。
-
内部是一个 while 循环,循环判断任务是否为空,若不为空,执行任务;
-
若取不到任务,或发生异常,退出循环,执行**processWorkerExit(w, completedAbruptly); **在这个方法里把工作线程移除掉。
读取任务的方式
主要有两种方式:一个是 firstTask,这个是工作线程第一次跑的时候执行的任务,最多只能执行一次,后面得从 getTask 方法里取任务。
getTask 是关键,在不考虑异常的场景下,返回,就表示退出循环,结束线程。
private Runnable getTask() {
boolean timedOut = false; // Did the last poll() time out?
for (;;) {
int c = ctl.get();
// Check if queue empty only if necessary.
if (runStateAtLeast(c, SHUTDOWN)
&& (runStateAtLeast(c, 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;
}
}
}
复制代码
重点关注的是 getTask 返回操作