可以看到,ctl 使用了 Integer 类型来保存,高 3 位保存 runState,低 29 位保存 workerCount。COUNT_BITS 就是 29,CAPACITY 就是 1 左移 29 位减 1(29 个 1),这个常量表示 workerCount 的上限值,大约是 5 亿。
运行状态 - 线程池一共有五种运行状态:
RUNNING - 运行状态。接受新任务,并且也能处理阻塞队列中的任务。
SHUTDOWN - 关闭状态。不接受新任务,但可以处理阻塞队列中的任务。
在线程池处于 RUNNING 状态时,调用 shutdown 方法会使线程池进入到该状态。
finalize 方法在执行过程中也会调用 shutdown 方法进入该状态。
STOP - 停止状态。不接受新任务,也不处理队列中的任务。会中断正在处理任务的线程。在线程池处于 RUNNING 或 SHUTDOWN 状态时,调用 shutdownNow 方法会使线程池进入到该状态。
TIDYING - 整理状态。如果所有的任务都已终止了,workerCount (有效线程数) 为 0,线程池进入该状态后会调用 terminated 方法进入 TERMINATED 状态。
TERMINATED - 已终止状态。在 terminated 方法执行完后进入该状态。默认 terminated 方法中什么也没有做。进入 TERMINATED 的条件如下:
线程池不是 RUNNING 状态;
线程池状态不是 TIDYING 状态或 TERMINATED 状态;
如果线程池状态是 SHUTDOWN 并且 workerQueue 为空;
workerCount 为 0;
设置 TIDYING 状态成功。
构造方法ThreadPoolExecutor 有四个构造方法,前三个都是基于第四个实现。第四个构造方法定义如下:
public ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, ThreadFactory threadFactory, RejectedExecutionHandler handler) {参数说明:
corePoolSize - 核心线程数量。当有新任务通过 execute 方法提交时 ,线程池会执行以下判断:
如果运行的线程数少于 corePoolSize,则创建新线程来处理任务,即使线程池中的其他线程是空闲的。
如果线程池中的线程数量大于等于 corePoolSize 且小于 maximumPoolSize,则只有当 workQueue 满时才创建新的线程去处理任务;
如果设置的 corePoolSize 和 maximumPoolSize 相同,则创建的线程池的大小是固定的。这时如果有新任务提交,若 workQueue 未满,则将请求放入 workQueue 中,等待有空闲的线程去从 workQueue 中取任务并处理;
如果运行的线程数量大于等于 maximumPoolSize,这时如果 workQueue 已经满了,则使用 handler 所指定的策略来处理任务;
所以,任务提交时,判断的顺序为 corePoolSize => workQueue => maximumPoolSize。
maximumPoolSize - 最大线程数量。
如果队列满了,并且已创建的线程数小于最大线程数,则线程池会再创建新的线程执行任务。
值得注意的是:如果使用了无界的任务队列这个参数就没什么效果。
keepAliveTime:线程保持活动的时间。
当线程池中的线程数量大于 corePoolSize 的时候,如果这时没有新的任务提交,核心线程外的线程不会立即销毁,而是会等待,直到等待的时间超过了 keepAliveTime。
所以,如果任务很多,并且每个任务执行的时间比较短,可以调大这个时间,提高线程的利用率。
unit - keepAliveTime 的时间单位。有 7 种取值。可选的单位有天(DAYS),小时(HOURS),分钟(MINUTES),毫秒(MILLISECONDS),微秒(MICROSECONDS, 千分之一毫秒)和毫微秒(NANOSECONDS, 千分之一微秒)。
workQueue - 等待执行的任务队列。用于保存等待执行的任务的阻塞队列。 可以选择以下几个阻塞队列。
ArrayBlockingQueue - 有界阻塞队列。
此队列是基于数组的先进先出队列(FIFO)。
此队列创建时必须指定大小。
LinkedBlockingQueue - 无界阻塞队列。
此队列是基于链表的先进先出队列(FIFO)。
如果创建时没有指定此队列大小,则默认为 Integer.MAX_VALUE。
吞吐量通常要高于 ArrayBlockingQueue。
使用 LinkedBlockingQueue 意味着: maximumPoolSize 将不起作用,线程池能创建的最大线程数为 corePoolSize,因为任务等待队列是无界队列。
Executors.newFixedThreadPool 使用了这个队列。
SynchronousQueue - 不会保存提交的任务,而是将直接新建一个线程来执行新来的任务。
每个插入操作必须等到另一个线程调用移除操作,否则插入操作一直处于阻塞状态。
吞吐量通常要高于 LinkedBlockingQueue。
Executors.newCachedThreadPool 使用了这个队列。
PriorityBlockingQueue - 具有优先级的无界阻塞队列。
threadFactory - 线程工厂。可以通过线程工厂给每个创建出来的线程设置更有意义的名字。