【JUC源码解析】ThreadPoolExecutor

简介

ThreadPoolExecutor,线程池的基石。

概述

线程池,除了用HashSet承载一组线程做任务以外,还用BlockingQueue承载一组任务。corePoolSize和maximumPoolSize,分别表示线程弛里存活的最小和最大线程数目,keepAliveTime表示不干活的线程的存活时间。当过来一个任务时,如果线程池里的线程数目小于corePoolSize,那么直接创建一个线程去处理它;如果线程数目大于等corePoolSize并且小于maximumPoolSize,那么,将这个任务放进任务队列里;如果任务队列已满,则继续创建线程处理该任务;如果线程弛数目等于maximumPoolSize,此时任务队列肯定已经满了,那么采取饱和策略。如果线程池里的线程空闲时间达到keepAliveTime,并且数量大于corePoolSize,此刻任务队列肯定是空的,那么销毁该线程。

线程池的控制状态

 1 // 线程池的控制状态,高3位表示运行状态,低29位表示线程的数量
 2     private final AtomicInteger ctl = new AtomicInteger(ctlOf(RUNNING, 0));
 3 
 4     private static final int COUNT_BITS = Integer.SIZE - 3; // 29位的偏移量
 5     private static final int CAPACITY = (1 << COUNT_BITS) - 1; // 最大容量
 6 
 7     private static final int RUNNING = -1 << COUNT_BITS; // 正在运行,接受新任务,并且处理任务队列里的任务
 8     private static final int SHUTDOWN = 0 << COUNT_BITS; // 关闭,不再接受新任务,但是处理队列里的任务
 9     private static final int STOP = 1 << COUNT_BITS; // 停止,不再接受新任务,不处理任务队列里的任务,并且中断正在运行的任务
10     private static final int TIDYING = 2 << COUNT_BITS; // 整理中,所有的任务都已经停止,线程数为0,并调用terminate(钩子)方法
11     private static final int TERMINATED = 3 << COUNT_BITS; // 终止,terminate方法运行完毕
12 
13     private static int runStateOf(int c) { // 获取线程池的运行状态
14         return c & ~CAPACITY;
15     }
16 
17     private static int workerCountOf(int c) { // 获取线程池的线程数量
18         return c & CAPACITY;
19     }
20 
21     private static int ctlOf(int rs, int wc) { // 反推线程池的控制状态
22         return rs | wc;
23     }

状态转换关系

RUNNING -> SHUTDOWN                     // shutdown()方法被调用
(RUNNING or SHUTDOWN) -> STOP    // shutdownNow()方法被调用
SHUTDOWN -> TIDYING                       // 线程池和任务队列都为空
STOP -> TIDYING                                   // 线程池为空
TIDYING -> TERMINATED                     // terminated()方法运行完毕

属性

 1     private final BlockingQueue<Runnable> workQueue; // 任务队列
 2     private final ReentrantLock mainLock = new ReentrantLock(); // 可重入锁
 3     private final HashSet<Worker> workers = new HashSet<Worker>(); // 线程集合
 4     private final Condition termination = mainLock.newCondition(); // 终止条件
 5     private int largestPoolSize; // 最大线程池容量
 6     private long completedTaskCount; // 已完成任务数量
 7     private volatile ThreadFactory threadFactory; // 线程工厂
 8     private volatile RejectedExecutionHandler handler; // 饱和策略
 9     private volatile long keepAliveTime; // 线程等待时间
10     private volatile boolean allowCoreThreadTimeOut; // 是否允许核心线程超时
11     private volatile int corePoolSize; // 核心线程池大小
12     private volatile int maximumPoolSize; // 最大线程池大小
13     private static final RejectedExecutionHandler defaultHandler = new AbortPolicy(); // 默认饱和策略

Worker

继承关系

 1 private final class Worker extends AbstractQueuedSynchronizer implements Runnable {} 

属性

1         final Thread thread; // 承载的线程
2         Runnable firstTask; // 首任务
3         volatile long completedTasks; // 已完成任务数量

构造方法

1         Worker(Runnable firstTask) {
2             setState(-1); // 执行任务之前,禁止中断
3             this.firstTask = firstTask; // 初始化首任务
4             this.thread = getThreadFactory().newThread(this);  // 初始化线程 
5         }

 主要方法

 1         public void run() { // 重写Runnable的run方法
 2             runWorker(this);
 3         }
 4 
 5         protected boolean isHeldExclusively() { // 是否被独占,0否,1是
 6             return getState() != 0;
 7         }
 8 
 9         protected boolean tryAcquire(int unused) { // 尝试获取锁
10             if (compareAndSetState(0, 1)) {
11                 setExclusiveOwnerThread(Thread.currentThread());
12                 return true;
13             }
14             return false;
15         }
16 
17         protected boolean tryRelease(int unused) { // 尝试释放锁
18             setExclusiveOwnerThread(null);
19             setState(0);
20             return true;
21         }
22 
23         public void lock() { // 获取锁
24             acquire(1);
25         }
26 
27         public boolean tryLock() { // 尝试获取锁
28             return tryAcquire(1);
29         }
30 
31         public void unlock() { // 释放锁
32             release(1);
33         }
34 
35         public boolean isLocked() { // 是否被独占
36             return isHeldExclusively();
37         }
38 
39         void interruptIfStarted() { // 中断
40             Thread t;
41             if (getState() >= 0 && (t = thread) != null && !t.isInterrupted()) {// 1. 状态大于等于0 2.线程不为空 3该线程没被中断
42                 try {
43                     t.interrupt(); // 中断
44                 } catch (SecurityException ignore) {
45                 }
46             }
47         }
48     }

 execute(Runnable)

 1     public void execute(Runnable command) {
 2         if (command == null)
 3             throw new NullPointerException();
 4         int c = ctl.get(); // 获取线程池的控制状态
 5         if (workerCountOf(c) < corePoolSize) { // 1. worker数量小于corePoolSize,
 6                                                 // 创建线程
 7             if (addWorker(command, true))
 8                 return; // 成功返回
 9             c = ctl.get(); // 失败,再次获取控制状态(调用addWorker方法,该状态更改过)
10         }
11         if (isRunning(c) && workQueue.offer(command)) {// 2.查看线程池是否处于运行状态,是则说明worker数量不满足条件1,因此任务入队;
12                                                        // 否则,线程池处于非运行状态,进入3(最后会reject);要么入队失败,也进入3(也许会成功)
13             int recheck = ctl.get(); // 再次获取控制状态,因为已经入队成功,万一状态改变,需要将任务出队(回滚)
14             if (!isRunning(recheck) && remove(command)) // 状态改变,回滚
15                 reject(command); // 拒绝 
16             else if (workerCountOf(recheck) == 0) // 入队成功,但线程池已空,此时需要创建线程处理它
17                 addWorker(null, false); // 创建线程
18         } else if (!addWorker(command, false)) // 若添加失败,拒绝
19             reject(command);
20     }

状态再检查,进一步推广到变量可见性。1.两次使用之间,显式更新了变量,此时要重新获取,以便得到最新值。2.根据此变量的值,执行某项策略,需要回过头来再次检查,如果改变,则回滚。(乐观锁)

addWorker(Runnable, boolean)

 1     private boolean addWorker(Runnable firstTask, boolean core) {
 2         retry: for (;;) { // A. runState变化,重试
 3             int c = ctl.get(); // ctl
 4             int rs = runStateOf(c); // runState
 5             // 等价于
 6             // if (!(rs < SHUTDOWN || (rs == SHUTDOWN && firstTask == null && !workQueue.isEmpty())))
 7             //     return false;
 8             // 也即是
 9             // if (rs < SHUTDOWN || (rs == SHUTDOWN && firstTask == null && !workQueue.isEmpty()))
10             // 接着往下走:a. rs == RUNNING; 或者,b. rs == SHUTDOWN, 并且,firstTask == null, 再并且工作队列不为空
11             // a. 不必解释
12             // b. rs == SHUTDOWN时,此时,不再接受新任务,但是,工作队列里的任务还是要处理的,若是线程池里没有线程了,还是需要新增线程处理这些任务的
13             // 如何与由新任务发起的创建线程做区分呢?答案就是firstTask是否为null,不为null就是新任务发起的
14             if (rs >= SHUTDOWN && !(rs == SHUTDOWN && firstTask == null && !workQueue.isEmpty()))
15                 return false;
16 
17             for (;;) { // B.workerCount变化,重试
18                 int wc = workerCountOf(c);
19                 if (wc >= CAPACITY || wc >= (core ? corePoolSize : maximumPoolSize)) // 校验workerCount
20                     return false;
21                 if (compareAndIncrementWorkerCount(c)) // 竞态点,可能失败:1.runState变化  -> A 2.workerCount变化  -> B
22                     break retry;
23                 c = ctl.get(); // 重新读取ctl
24                 if (runStateOf(c) != rs) // 如果runState发生变化,转向A;否则,转向B
25                     continue retry;
26             }
27         }
28 
29         boolean workerStarted = false; // 记录该线程是否已经启动
30         boolean workerAdded = false; // 记录是否添加成果
31         Worker w = null;
32         try {
33             w = new Worker(firstTask); // 新建工作者
34             final Thread t = w.thread; // 工作者线程
35             if (t != null) { // 若线程为空,直接失败 
36                 final ReentrantLock mainLock = this.mainLock; // 可重入锁
37                 mainLock.lock(); // 因为要对workers操作,加锁
38                 try {
39                     int rs = runStateOf(ctl.get()); // 再次读取runState, 因为在此过程中,可能会有别的线程操作此变量
40                     if (rs < SHUTDOWN || (rs == SHUTDOWN && firstTask == null)) { // C 第二次校验runState,与上面不同的是,这次没有校验工作队列是否为空
41                         if (t.isAlive()) // 检验该线程是否已经启动,正常没有启动
42                             throw new IllegalThreadStateException();
43                         workers.add(w); // 添加到线程池里
44                         int s = workers.size(); // 工作者的实际数量
45                         if (s > largestPoolSize)
46                             largestPoolSize = s; // 记录工作者最大数量
47                         workerAdded = true; // 添加成功
48                     }
49                 } finally {
50                     mainLock.unlock(); // 解锁,别的线程可以操作workers了
51                 }
52                 if (workerAdded) { // 如果添加成功
53                     t.start(); // 启动线程
54                     workerStarted = true; // 线程启动成功
55                 }
56             }
57         } finally {
58             if (!workerStarted) // 如果线程启动失败
59                 addWorkerFailed(w); // 回滚
60         }
61         return workerStarted; // 返回结果
62     }

代码注释C处,第二次校验runState时,为什么没有校验工作队列workQueue了呢?

考虑这样一种场景

  1. 线程池里的线程没有空闲的,都在工作,执行任务。
  2. 其中一个线程由于某种原因,跳出了while 循环。也许是某一时刻,workQueue里的任务被其他线程取空了,到此线程时,阻塞在workQueue.take()方法上了,而后又刚好遇到中断(各种原因),于是返回null并跳出了循环。
  3. 后来,workQueue又持续添加了新的任务,其他线程接着工作,中间没收到打扰。
  4. 接着,runState变为SHUTDOWN或者在第8步之后变为SHUTDOWN,此时还是RUNNING ,那个跳出循环的线程,我们暂且称为JUMP线程吧,走到addWork(null,false)方法。
  5. 在双重for循环检测时,恰巧满足条件
    if (rs < SHUTDOWN || (rs == SHUTDOWN && firstTask == null && !workQueue.isEmpty()))
    于是,会继续往下执行,此时,其他的线程仍在紧锣密鼓地工作。
  6. 注意,JUMP线程已经执行过tryTerminate()方法了,并且此线程马上就消亡了,调用addWork(null,false)方法也是为了创建新的线程替代它的。
  7. JUMP线程走到创建工作者那里时,也就是再次(第二次)检验runState的地方。
  8. 恰巧这时,workQueue被其他线程取空了,更巧的是,所有其他的线程都阻塞在了workQueue.take()方法上,从getTask() 方法逻辑可知,这是发生在runState变为SHUTDOWN之前,不然后面的线程会检查runState状态,直接return null了。
  9. 好了,时间停在了这一刻:JUMP线程准备第二次校验runState,其他线程阻塞在workQueue.take()方法上;不过,在runState变为SHUTDOWN时,也就是调用shutdown()方法,会调用tryTerminate()方法。
  10. 在tryTerminate()方法里,检查runState为SHUTDOWN,workQueue为空,但threadPool不为空,于是会走interruptIdleWorkers(ONLY_ONE)方法,随意中断一个空闲线程,注意,这里没有走到terminated()方法。
  11. 一个阻塞在workQueue.take()方法上的线程被唤醒,并跳出while循环,runWorker(Worker)里的逻辑,然后调用tryTerminate()方法,同步骤10,接着调用addWorker(null, false),当然在方法开始处,双重for循环那里就返回了,因为不满足条件,此刻workQueue已经为空。
  12. 就这样,10->11->10->11,一个接一个地调用,中断后面的阻塞着的线程并传播下去,直到最后一个,调用tryTerminate()方法,由于workCount不为0.,因为JUMP线程在双重for循环那里通过了检查,使得workCount加1了,于是,这最后一个被中断叫醒的线程也是走的第10步,只是没有空闲线程可以中断了。
  13. 最后,JUMP在第二次检查runState时,不应该再检查workQueue是否为空了,如果检查,由于workQueue为空,那么将会回滚,JUMP线程没有加入到threadPool里面去,那么便没有线程调用最终的terminated()方法了。
  14. 由于都是异步的,以上步骤并不具有严格的时间顺序。
  15. 第13步有误,即便由于检查了workQueue为空而回滚,也会调用terminated()方法的,因为回滚的时候会调用addWorkerFailed(Worker)方法,这个方法会调用tryTerminate()方法,因为此时满足了条件继而terminated()方法。
  16. 但是不检查workQueue是否为空也没错,因为两方面费的力气差不多,因此,只在必要的时候检查workQueue,就像第一次那样。

addWorkerFailed(Worker)

 

 1     private void addWorkerFailed(Worker w) {
 2         final ReentrantLock mainLock = this.mainLock;
 3         mainLock.lock();
 4         try {
 5             if (w != null)
 6                 workers.remove(w);
 7             decrementWorkerCount();
 8             tryTerminate();
 9         } finally {
10             mainLock.unlock();
11         }
12     }

 

runWorker(Worker w)

 1     final void runWorker(Worker w) {
 2         Thread wt = Thread.currentThread(); // 当前线程
 3         Runnable task = w.firstTask; // 首任务
 4         w.firstTask = null; // 置位
 5         w.unlock(); // 允许中断(interruptIdleWorkers()方法),因为即便不unlock(),也阻止不了interruptWorkers()方法中断此线程
 6         boolean completedAbruptly = true; // 是否是突然完成,即异常情况
 7         try {
 8             while (task != null || (task = getTask()) != null) { // 如果首任务不为空,执行首任务;否则,从任务队列里取任务
 9                 w.lock(); // 加锁,防止中断(interruptIdleWorkers()方法)
10                 // 如果线程池停止了,中断此线程,否则,复位可能的中断,若此线程中断过,需要再次检查线程池是否停止
11                 // 有可能这边刚把中断复位,那边就把线程池停止了
12                 // !第一次检查线程池是否停止,是因为,线程池停止了,应该直接中断此线程
13                 // !第二次检查线程池是否停止,是因为,如果线程被中断了,刚好把它复位,很有可能是前一瞬间线程池停止导致的中断,所以要再次确认线程池的状态
14                 if ((runStateAtLeast(ctl.get(), STOP) || (Thread.interrupted() && runStateAtLeast(ctl.get(), STOP)))
15                         && !wt.isInterrupted())
16                     wt.interrupt();
17                 try {
18                     beforeExecute(wt, task); // 前置钩子
19                     Throwable thrown = null;
20                     try {
21                         task.run(); // 执行任务
22                     } catch (RuntimeException x) {
23                         thrown = x;
24                         throw x;
25                     } catch (Error x) {
26                         thrown = x;
27                         throw x;
28                     } catch (Throwable x) {
29                         thrown = x;
30                         throw new Error(x);
31                     } finally {
32                         afterExecute(task, thrown); // 后置钩子
33                     }
34                 } finally {
35                     task = null;
36                     w.completedTasks++;
37                     w.unlock(); // 释放锁,允许中断(interruptIdleWorkers()方法)
38                 }
39             }
40             completedAbruptly = false; // 平滑结束
41         } finally {
42             processWorkerExit(w, completedAbruptly); // 处理后续工作
43         }
44     }

getTask()

 1     private Runnable getTask() {
 2         boolean timedOut = false; // 记录上次workQueue.poll是否超时
 3 
 4         for (;;) { // 循环
 5             int c = ctl.get(); // 得到ctl
 6             int rs = runStateOf(c); // 得到runState
 7 
 8             // 等价于,if !(rs < SHUTDOWN || (rs < STOP && !workQueue.isEmpty()))
 9             // 即是,if !(rs == RUNNING || (rs == SHUTDOWN && !workQueue.isEmpty()))
10             if (rs >= SHUTDOWN && (rs >= STOP || workQueue.isEmpty())) {
11                 decrementWorkerCount(); // workerCount - 1
12                 return null; // 返回null
13             }
14 
15             int wc = workerCountOf(c); // 得到workerCount
16 
17             // 是否允许超时
18             boolean timed = allowCoreThreadTimeOut || wc > corePoolSize;
19 
20             // 1. workerCount > maximumPoolSize
21             // 2. timed为真,并且timeOut也为真,即上次已超时,而且,此刻workerCount大于1,或者workQueue为空
22             if ((wc > maximumPoolSize || (timed && timedOut)) && (wc > 1 || workQueue.isEmpty())) {
23                 if (compareAndDecrementWorkerCount(c)) // workerCount减1
24                     return null;
25                 continue; // 否则,重试
26             }
27 
28             try {
29                 Runnable r = timed ? workQueue.poll(keepAliveTime, TimeUnit.NANOSECONDS) : workQueue.take(); // 允许超时,调用poll()方法,否则take()方法
30                 if (r != null)
31                     return r; // 不为空,返回
32                 timedOut = true; // 否则,继续
33             } catch (InterruptedException retry) {
34                 timedOut = false; // 中断,清除超时标记
35             }
36         }

processWorkerExit(Worker, boolean)

 1     private void processWorkerExit(Worker w, boolean completedAbruptly) {
 2         if (completedAbruptly) // 如果是异常结束,需要调整workCount(-1),因为正常结束的,会在getTask()方法里调用decrementWorkerCount()方法
 3             decrementWorkerCount();
 4         final ReentrantLock mainLock = this.mainLock; // 可重入锁,因为要对works操作
 5         mainLock.lock(); // 加锁
 6         try {
 7             completedTaskCount += w.completedTasks; // 添加当前线程完成的任务数量加到总的完成任务数量
 8             workers.remove(w); // 从线程池中移除该线程
 9         } finally {
10             mainLock.unlock(); // 释放锁
11         }
12 
13         tryTerminate(); // 调用tryTerminate()方法,看是否满足结束条件
14 
15         int c = ctl.get(); // 获得ctl
16         if (runStateLessThan(c, STOP)) { // 线程池没有停止
17             if (!completedAbruptly) { // 该线程平滑结束
18                 int min = allowCoreThreadTimeOut ? 0 : corePoolSize; // 得出最小线程数
19                 if (min == 0 && !workQueue.isEmpty()) // 最少保留1个
20                     min = 1;
21                 if (workerCountOf(c) >= min) // 如果不小于最小线程数,不必再添加
22                     return;
23             }
24             addWorker(null, false); // 如果是异常结束,则说明任务队列里应该还有任务,那么直接添加新的线程替换它
25         }
26     }

shutdown()

 1     public void shutdown() {
 2         final ReentrantLock mainLock = this.mainLock;
 3         mainLock.lock(); // 获得锁
 4         try {
 5             checkShutdownAccess(); // 检查权限
 6             advanceRunState(SHUTDOWN); // 设置状态
 7             interruptIdleWorkers(); // 中断空闲线程
 8             onShutdown(); // 钩子 ScheduledThreadPoolExecutor
 9         } finally {
10             mainLock.unlock(); // 释放锁
11         }
12         tryTerminate(); // 尝试终止线程池
13     }

shutdownNow()

 1     public List<Runnable> shutdownNow() {
 2         List<Runnable> tasks; // 存放未执行的任务
 3         final ReentrantLock mainLock = this.mainLock;
 4         mainLock.lock(); // 获得锁
 5         try {
 6             checkShutdownAccess(); // 检查权限
 7             advanceRunState(STOP); // 设置状态
 8             interruptWorkers(); // 中断线程
 9             tasks = drainQueue(); // 拉取任务队列里的任务
10         } finally {
11             mainLock.unlock(); // 释放锁
12         }
13         tryTerminate(); // 尝试终止线程池
14         return tasks; // 返回任务列表
15     }

interruptIdleWorkers()

 1     private void interruptIdleWorkers() {
 2         interruptIdleWorkers(false);
 3     }
 4 
 5     private void interruptIdleWorkers(boolean onlyOne) {
 6         final ReentrantLock mainLock = this.mainLock;
 7         mainLock.lock(); // 获得可重入锁
 8         try {
 9             for (Worker w : workers) {
10                 Thread t = w.thread;
11                 if (!t.isInterrupted() && w.tryLock()) { // 线程没被中断,并且获得锁
12                     try {
13                         t.interrupt(); // 中断线程
14                     } catch (SecurityException ignore) {
15                     } finally {
16                         w.unlock(); // 释放锁
17                     }
18                 }
19                 if (onlyOne) // 如果仅仅中断一个,跳出循环
20                     break;
21             }
22         } finally {
23             mainLock.unlock(); // 释放可重入锁
24         }
25     }

interruptWorkers()

 1     private void interruptWorkers() {
 2         final ReentrantLock mainLock = this.mainLock; // 获得可重入锁
 3         mainLock.lock(); // 加锁
 4         try {
 5             for (Worker w : workers)
 6                 w.interruptIfStarted(); // 只要线程已经启动,就中断它
 7         } finally {
 8             mainLock.unlock(); // 释放锁
 9         }
10     }

tryTerminate()

 1     final void tryTerminate() {
 2         for (;;) {
 3             int c = ctl.get(); // 获得ctl
 4             // 1. 线程池正在运行
 5             // 2. 线程池已经结束或正在整理
 6             // 3. 线程池已经SHUTDOWN,但是workQueue不为空
 7             if (isRunning(c) || runStateAtLeast(c, TIDYING) || (runStateOf(c) == SHUTDOWN && !workQueue.isEmpty()))
 8                 return;
 9             // workerCount不等于0,只中断一个空闲线程,保证中断传播下去
10             if (workerCountOf(c) != 0) {
11                 interruptIdleWorkers(ONLY_ONE);
12                 return;
13             }
14 
15             final ReentrantLock mainLock = this.mainLock; // 可重入锁
16             mainLock.lock(); // 加锁
17             try {
18                 if (ctl.compareAndSet(c, ctlOf(TIDYING, 0))) { // 设置状态为TIDYING
19                     try {
20                         terminated(); // 调用terminated()方法,钩子,用户实现
21                     } finally {
22                         ctl.set(ctlOf(TERMINATED, 0)); // 设置状态为TERMINATED
23                         termination.signalAll(); // 通知信号
24                     }
25                     return;
26                 }
27             } finally {
28                 mainLock.unlock(); // 解锁
29             }
30         }
31     }

 

行文至此结束。

 

尊重他人的劳动,转载请注明出处:http://www.cnblogs.com/aniao/p/aniao_tpe.html

 

posted @ 2018-01-03 21:52  林城画序  阅读(399)  评论(0编辑  收藏  举报