概述
这篇文章是我在阅读源码时整理的一些笔记,对源码的关键点进行了比较详细的注释,然后加上一些自己对线程池机制的理解。最终目的是要弄清楚下面这些问题:
- 线程池有 execute() 和 submit() 方法,执行机制分别是什么?
- 如何新建线程?
- 任务如何执行?
- 线程如何销毁?超时机制如何实现?
首先需要介绍一下线程池的两个重要成员:
ctl
AtomicInteger 类型。高3位存储线程池状态,低29位存储当前线程数量。workerCountOf(c) 返回当前线程数量。runStateOf(c) 返回当前线程池状态。 线程池有如下状态:
- RUNNING:接收新任务,处理队列任务。
- SHUTDOWN:不接收新任务,但处理队列任务。
- STOP:不接收新任务,也不处理队列任务,并且中断所有处理中的任务。
- TIDYING:所有任务都被终结,有效线程为0。会触发terminated()方法。
- TERMINATED:当terminated()方法执行结束。
Worker
这个线程在线程池中的包装类。一个 Worker 代表一个线程。线程池用一个 HashSet 管理这些线程。
需要注意的是,Worker 本身并不区分核心线程和非核心线程,核心线程只是概念模型上的叫法,特性是依靠对线程数量的判断来实现的 Worker 特性如下:
- 继承自 AQS,本身实现了一个最简单的不公平的不可重入锁。
- 构造方法传入 Runnable,代表第一个执行的任务,可以为空。构造方法中新建一个线程。
- 实现了 Runnable 接口,在新建线程时传入 this。因此线程启动时,会执行 Worker 本身的 run 方法。
- run 方法调用了 ThreadPoolExecutor 的 runWorker 方法,负责实际执行任务。
submit() 方法的执行机制
submit 返回一个 Future 对象,我们可以调用其 get 方法获取任务执行的结果。代码很简单,就是将 Runnable 包装成 FutureTask 而已。可以看到,最终还是调用 Execute 方法:
public Future<?> submit(Runnable task) {
if (task == null) throw new NullPointerException();
RunnableFuture<Void> ftask = newTaskFor(task, null);
execute(ftask);
return ftask;
}
复制代码
FutureTask 的代码就不贴了,简述一下原理:
- FutureTask 实现了 RunnableFuture 接口,RunnableFuture 继承自Runnable。执行任务时会调用 FutureTask 的 run 方法,run 方法中执行真正的任务代码,执行完后调用 set 方法设置结果。
- 如果任务执行完毕,get 方法会直接返回结果,如果没有,get 方法会阻塞并等待结果。
- set 方法中设置结果后会取消阻塞,使 get 方法返回结果。
execute() 方法的执行机制
这个机制大家应该都很熟了,再简述一遍:
- 工作线程数小于核心线程数时,直接新建核心线程执行任务;
- 大于核心线程数时,将任务添加进等待队列;
- 队列满时,创建非核心线程执行任务; <

最低0.47元/天 解锁文章
3512

被折叠的 条评论
为什么被折叠?



