Executors 其实是个工 具 类,里面提 供了好多静态
方法,这些方法根据用 户 选择返回不同的线程池实例 。 ThreadPoo!Executor 继承了
Abs tractExecutorService ,成员变量 ct! 是一个 Integer 的原子变量 ,用 来记录线程池状态和
线程池中线程个数,类似于 ReentrantReadWriteLock 使用 一个变量来保存两种信息。
结构
public class ThreadPoolExecutor extends AbstractExecutorService {
//( 高3位)用来表示线程池状态, (低29位)用来表示线程个数
//默认是RUNNING状态,线程个数为 0
private final AtomicInteger ctl = new AtomicInteger(ctlOf(RUNNING, 0));
//线程个数掩码位数,并不是所有平台 的工的类型都是32位的,所以准确地说, 是具体平台 下 Integer的二进制位数- 3后的剩余位数所表示的数才是线程的个数
private static final int COUNT_BITS = Integer.SIZE - 3;
//线程最大个数(低29位) 00011111111111111111111111111111
private static final int CAPACITY = (1 << COUNT_BITS) - 1;
//线程池状态 :
// runState is stored in the high-order bits
//(高 3位) : 11100000000000000000000000000000
private static final int RUNNING = -1 << COUNT_BITS;
//( 高3位) : 00000000000000000000000000000000
private static final int SHUTDOWN = 0 << COUNT_BITS;
//(高 3位) : 00100000000000000000000000000000
private static final int STOP = 1 << COUNT_BITS;
//( 高 3位) : 01000000000000000000000000000000
private static final int TIDYING = 2 << COUNT_BITS;
//( 高 3位) : 01100000000000000000000000000000
private static final int TERMINATED = 3 << COUNT_BITS;
// Packing and unpacking ctl
//获取高 3位(运行状态)
private static int runStateOf(int c) { return c & ~CAPACITY; }
///获取低29位(线程个数)
private static int workerCountOf(int c) { return c & CAPACITY; }
//计算ctl新值(线斗呈状态与线程个数 )
private static int ctlOf(int rs, int wc) { return rs | wc; }
...
线程池状态含义如下
- RUNNING : 接受新任务并且处理阻塞队列里的任务 。
- SHUTDOWN :拒绝新任务但是处理阻塞队列里的任务 。
- 拒绝新任务并且抛弃阻塞队列里 的任务 ,同时会中断正在处理的任务。
- TIDYING : 所有任务都执行完(包含阻塞队列里面的任务)后当前线程池活动线程
数为 0 , 将要调用 terminated 方法 。
TERMINATED : 终止状态 。 terminated 方法调用完成 以后的状态.
线程池状态转换列举如下
- RUNNING -> SHUTDOWN : 显式调用 shutdown() 方法 , 或者隐式调用了 finalize()
方法里面的 shutdown() 方法 。 - RUNNING 或 SHUTDOWN)-> STOP : 显式调用 shutdownNow() 方法时.
- SHUTDOWN -> TIDYING : 当线程池和任务队列都为空时 。
- STOP -> TIDYING : 当线程池为空时 。
- TIDYING > TERMINATED> 当 terminated() hook 方法执行完成时 。
线程池的参数
- corePoo lSize :线程池核心线程个数
- workQueue :用于保存等待执行的任务的阻 塞 队列,比如基于数组的有界ArrayBlock ingQueue 、基于链表的无界 LinkedBlockingQueue 、最多只有一个元素的同步队列 SynchronousQueue 及优先级队列 PriorityBlockingQueue 等
- maximunPoolSize : 线程池最大线程数量
- ThreadFactory :创建线程的工厂
- RejectedExecutionHandler :饱和策略 , 当 队列满并且线程个数达到 maximunPoolSize后采取 的策略, 比如 AbortPolicy (抛出异常〉、 CallerRunsPolicy (使用调用者所在线程来运行任务) 、 DiscardOldestPolicy (调用 poll 丢弃一个任务,执行当前任务)及 DiscardPolicy (默默丢弃,不抛出异常〉
- keeyAliveTime :存活时间 。 如果当前线程池中的线程数量比核心线程数量多 ,并且是闲置状态, 则这些闲置的线程能存活的最大时间
- TimeUnit : 存活时间的时间单位 。
线程池类型
- newFixedThreadPool :创建一个核心线程个数和最大线程个数都为 nThreads 的线程池,并且阻塞 队列长度为 Integer.MAX_VALUE.keeyAliveTime =0,说明只要线程个数比核心线程个数多并且当前空闲则 回收.
public static ExecutorService newFixedThreadPool(int nThreads) {
return new ThreadPoolExecutor(nThreads, nThreads,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>());
}
public static ExecutorService newFixedThreadPool(int nThreads, ThreadFactory threadFactory) {
return new ThreadPoolExecutor(nThreads, nThreads,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>(),
threadFactory);
}
- newSingleThreadExecutor:创建一个核心线程个数和最大线程个数都为 1 的线程池 ,并且阻塞队列长度为 Integer.MAX_VALUE 。 keeyA liveTime=O 说明只要线程个数比核心线程个数多并且当前空闲 则 回收。
public static ExecutorService newSingleThreadExecutor() {
return new FinalizableDelegatedExecutorService
(new ThreadPoolExecutor(1, 1,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>()));
}
public static ExecutorService newSingleThreadExecutor(ThreadFactory threadFactory) {
return new FinalizableDelegatedExecutorService
(new ThreadPoolExecutor(1, 1,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>(),
threadFactory));
}
public static ScheduledExecutorService newSingleThreadScheduledExecutor() {
return new DelegatedScheduledExecutorService
(new ScheduledThreadPoolExecutor(1));
}
- newCachedThreadPoo: 创建一个按需创建线程的线程池,初始线程个数为 0 , 最多线程个数为 Integer.MAX_VALUE,并且阻塞队列为同步队列 。 keeyAliveTime=60说明只要当前线程在 60s 内空闲则回收。这个类型的特殊之处在于 , 加入同步队列
的任务会被马上执行,同步队列里面最多只有一个任务。
public static ExecutorService newCachedThreadPool() {
return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
60L, TimeUnit.SECONDS,
new SynchronousQueue<Runnable>());
}
public static ExecutorService newCachedThreadPool(ThreadFactory threadFactory) {
return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
60L, TimeUnit.SECONDS,
new SynchronousQueue<Runnable>(),
threadFactory);
}
其中 mainLock 是独占锁 , 用来控制新增 Worker
线程操作的原子性 。 termination 是该锁对应 的 条件队列 , 在线程调用 awaitTermination 时
用 来存放阻塞 的线程 。
Worker 继承 AQS 和 Runnable 接口 , 是具体承载 任务的 对象。 Worker 继 承 了 AQS,
自 己实现 了简单不可重入独占锁 , 其中 state=O 表示锁未被获取状态 , state=l 表示锁 己经
被获取的状态, state二l 是创建 Worker 时默认的状态 ,创建时状态设置为一l 是为了避免
该线程在运行 runWorker() 方法前被 中 断 ,下面会具体讲解。其 中变量 自rstTask 记录该工
作线程执行的第一个任务 , thread 是具体执行任务的线程。
DefaultThreadFactory 是 线程工厂 , newThread 方 法是对 线程 的 一 个修饰 。 其中
poo!Number 是个静态 的 原子变量 , 用来统计线程工厂 的个数 , threadNumber 用 来记录每
个线程工厂创建了多少线程 , 这两个值也作为线程池和线程的名称的一部分
public void execute(Runnable command)
execute 方法的作用是 提交任务 command 到线程池进行执 行。
ThreadPoo!Executor 的实现实际是一个生产消费模型, 当用户添加
任务到线程池时相当于生产者生产元素, workers 线程工作集中的线程直接执行任务或者
从任务队列里面获取任务时则相当于消费者消费元素。
public void execute(Runnable command) {
//1 如采任务为 null ,则抛出 NPE异常
if (command == null)
throw new NullPointerException();
/*
* Proceed in 3 steps:
*
* 1. If fewer than corePoolSize threads are running, try to
* start a new thread with the given command as its first
* task. The call to addWorker atomically checks runState and
* workerCount, and so prevents false alarms that would add
* threads when it shouldn't, by returning false.
*
* 2. If a task can be successfully queued, then we still need
* to double-check whether we should have added a thread
* (because existing ones died since last checking) or that
* the pool shut down since entry into this method. So we
* recheck state and if necessary roll back the enqueuing if
* stopped, or start a new thread if there are none.
*
* 3. If we cannot queue task, then we try to add a new
* thread. If it fails, we know we are shut down or saturated
* and so reject the task.
*/
//2 获取当前线程池的状态+线程个数变量组合值
int c = ctl.get();
//3 当前线程池中线程个数是否 小于corePoolSize ,小于则开启新线程运行
if (workerCountOf(c) < corePoolSize) {
if (addWorker(command, true))
return;
c = ctl.get();
}
//4. 如果线程池处于RUNNING状态,则添加任务到阻塞队 91]
if (isRunning(c) && workQueue.offer(command)) {
//4.1 二次检查
int recheck = ctl.get();
//4.2 如果当前线程;也状态不是RUNNING!il1J从队§1]中删除任务,并执行拒绝策略
if (! isRunning(recheck) && remove(command))
reject(command);
//4.3 否则如果当前线程池为空 , 则添加一个线程
else if (workerCountOf(recheck) == 0)
addWorker(null, false);
}
//如果队列满 , 如j 新增线程 , 新增失败则执行拒绝策略
else if (!addWorker(command, false))
reject(command);
}
- addWorker
private boolean addWorker(Runnable firstTask, boolean core) {
//第一部分双重循环的目的是通过 CAS 操作增加线程数:
retry:
for (;;) {
int c = ctl.get();
int rs = runStateOf(c);
// Check if queue empty only if necessary.
if (rs >= SHUTDOWN &&
! (rs == SHUTDOWN &&
firstTask == null &&
! workQueue.isEmpty()))
return false;
for (;;) {
int wc = workerCountOf(c);
if (wc >= CAPACITY ||
wc >= (core ? corePoolSize : maximumPoolSize))
return false;
if (compareAndIncrementWorkerCount(c))
break retry;
c = ctl.get(); // Re-read ctl
if (runStateOf(c) != rs)
continue retry;
// else CAS failed due to workerCount change; retry inner loop
}
}
//第二部分主要是把并发安全的任务添加到 workers 里面,并且启动任务执行 到这里说明CAS成功了
boolean workerStarted = false;
boolean workerAdded = false;
Worker w = null;
try {
w = new Worker(firstTask);
final Thread t = w.thread;
if (t != null) {
final ReentrantLock mainLock = this.mainLock;
mainLock.lock();
try {
// Recheck while holding lock.
// Back out on ThreadFactory failure or if
// shut down before lock acquired.
int rs = runStateOf(ctl.get());
if (rs < SHUTDOWN ||
(rs == SHUTDOWN && firstTask == null)) {
if (t.isAlive()) // precheck that t is startable
throw new IllegalThreadStateException();
workers.add(w);
int s = workers.size();
if (s > largestPoolSize)
largestPoolSize = s;
workerAdded = true;
}
} finally {
mainLock.unlock();
}
if (workerAdded) {
t.start();
workerStarted = true;
}
}
} finally {
if (! workerStarted)
addWorkerFailed(w);
}
return workerStarted;
}
第一部分双重循环的目的是通过 CAS 操作增加线程数:
第二部分主要是把并发安全的任务添加到 workers 里面,并且启动任务执行
工作线程 Worker 的执行
Worker(Runnable firstTask) {
setState(-1); // inhibit interrupts until runWorker 在调用 runWorker前禁止中 断
this.firstTask = firstTask;
this.thread = getThreadFactory().newThread(this); //创建一个新的线程
}
在构造函数内 首先设置 Worker 的状态为 一i ,这 是为了避免当前 Worker 在调用
rnnWorker 方法前被中断(当其他线程调用了线程池的 shutdownNow 时-,如果 Worker 状
态 >=O 则会中|新该线程) 。这里设置了线程的状态为 - 1 ,所以该线程就不会被中断了 。 在
如下 rnnWorker 代码中,运行代码( 9 ) 时会调用 unlock 方法,该方法把 status 设置为了。,
所以这时候调用 shutdownNow 会中断 Worker 线程。
拒绝策略
不能有无限大小的缓存队列,因为如果有大量的任务进来,会导致内存的激增,如果一直激增而没有释放,会导致内存异常。
所以当发现负载到了一定的程度后,应该选择丢弃一些任务,而不是放在内存中,看着内存被耗掉,丢弃的时候希望把这些丢掉的任务(比如数量,具体是那些)记录下来。
- AbortPolicy :默认策略
public static class AbortPolicy implements RejectedExecutionHandler {
/**
* Creates an {@code AbortPolicy}.
*/
public AbortPolicy() { }
/**
* Always throws RejectedExecutionException.
*
* @param r the runnable task requested to be executed
* @param e the executor attempting to execute this task
* @throws RejectedExecutionException always
*/
public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
throw new RejectedExecutionException("Task " + r.toString() +
" rejected from " +
e.toString());
}
}
这个策略是如果不能执行了,就会抛出异常,并且将具体的任务信息打印出啦
- CallerRunsPolicy
public static class CallerRunsPolicy implements RejectedExecutionHandler {
/**
* Creates a {@code CallerRunsPolicy}.
*/
public CallerRunsPolicy() { }
/**
* Executes task r in the caller's thread, unless the executor
* has been shut down, in which case the task is discarded.
*
* @param r the runnable task requested to be executed
* @param e the executor attempting to execute this task
*/
public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
if (!e.isShutdown()) {
r.run();
}
}
}
if (!e.isShutdown()) {
r.run();
}
如果线程池还活着,就让调用者执行这个任务,这个类本身自己不做处理。
- DiscardPolicy
public static class DiscardPolicy implements RejectedExecutionHandler {
/**
* Creates a {@code DiscardPolicy}.
*/
public DiscardPolicy() { }
/**
* Does nothing, which has the effect of discarding task r.
*
* @param r the runnable task requested to be executed
* @param e the executor attempting to execute this task
*/
public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
}
}
这个策略是如果不执行了,就直接丢弃掉,设么也不做。
- DiscardOldestPolicy
public static class DiscardOldestPolicy implements RejectedExecutionHandler {
/**
* Creates a {@code DiscardOldestPolicy} for the given executor.
*/
public DiscardOldestPolicy() { }
/**
* Obtains and ignores the next task that the executor
* would otherwise execute, if one is immediately available,
* and then retries execution of task r, unless the executor
* is shut down, in which case task r is instead discarded.
*
* @param r the runnable task requested to be executed
* @param e the executor attempting to execute this task
*/
public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
if (!e.isShutdown()) {
e.getQueue().poll();
e.execute(r);
}
}
}
这个策略是 将队列中最老的丢弃掉。
ThreadFactory 线程工厂
static class DefaultThreadFactory implements ThreadFactory {
private static final AtomicInteger poolNumber = new AtomicInteger(1);
private final ThreadGroup group;
private final AtomicInteger threadNumber = new AtomicInteger(1);
private final String namePrefix;
DefaultThreadFactory() {
//为线程命名
SecurityManager s = System.getSecurityManager();
group = (s != null) ? s.getThreadGroup() :
Thread.currentThread().getThreadGroup();
namePrefix = "pool-" +
poolNumber.getAndIncrement() +
"-thread-";
}
//创建新的线程 能够在创造Thread的时候给Thread命名,或者使其变成守护线程的操作
public Thread newThread(Runnable r) {
Thread t = new Thread(group, r,
namePrefix + threadNumber.getAndIncrement(),
0);
if (t.isDaemon())
t.setDaemon(false);
if (t.getPriority() != Thread.NORM_PRIORITY)
t.setPriority(Thread.NORM_PRIORITY);
return t;
}
}