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