JUC下的ThreadPoolExecutor源码分析
基于版本JDK1.8
线程池执行流程:
1、查看线程池的execute方法
/** *如果任务无法提交执行,可能是因为执行器已关闭,或者由于其容量已达到 */ public void execute(Runnable command) { if (command == null) throw new NullPointerException(); /* * Proceed in 3 steps: * 1. 如果线程数量小于核心线程数,以给定的command启动线程,并设置为线程的第一个任务 * 2. 核心线程已满,则执行入队,成功入队则检查是否需要添加一个线程 * 3. 创建非核心线程,以给定的command启动线程,并设置为线程的第一个任务,如果创建非核心线程失败,则执行拒绝策略 */ int c = ctl.get(); if (workerCountOf(c) < corePoolSize) { if (addWorker(command, true)) return; c = ctl.get(); } if (isRunning(c) && workQueue.offer(command)) { int recheck = ctl.get(); //线程池如果不是RUNNING状态,从阻塞队列中把刚加入的任务移除,执行拒绝策略 if (!isRunning(recheck) && remove(command)) reject(command); //如果线程数量是否为空,此时又因为workQueue.offer(command)添加了一个任务,就需要添加一个非核心线程 //什么时候会出现这种情况呢, //如:executor.allowCoreThreadTimeOut(true);允许核心线程在空闲时间超过keepAliveTime后,会被终止,因此可能出现线程池没有线程的情况 else if (workerCountOf(recheck) == 0) addWorker(null, false); } else if (!addWorker(command, false)) reject(command); }
2、继续查看addworker方法
/** * 在线程池中创建一个新的线程 * @param firstTask参数为新增线程执行的第一个任务 * @param 活动线程数>=(core?核心线程数:最大线程数) */ private boolean addWorker(Runnable firstTask, boolean core) { retry: for (;;) { int c = ctl.get(); int rs = runStateOf(c); // x步骤 // 说人话就是线程池不是RUNNING状态,并且(状态不为SHUTDOWN 或者 任务不为空 或者 队列为空),则直接返回false if (rs >= SHUTDOWN && ! (rs == SHUTDOWN && firstTask == null && ! workQueue.isEmpty())) return false; for (;;) { //获取现有线程数 int wc = workerCountOf(c); //a步骤 //1、添加核心线程,则判断线程数是否超过核心线程数 //2、添加非核心线程,则判断线程数是否超过最大线程数 //是,则返回false if (wc >= CAPACITY || wc >= (core ? corePoolSize : maximumPoolSize)) return false; //b步骤 //cas增加线程数量成功,则通过break retry跳出多重循环,继续执行下方代码 if (compareAndIncrementWorkerCount(c)) break retry; c = ctl.get(); //如果状态没有变化,则继续执行步骤a或b //如果状态有变化,则跳出for循环,执行x步骤 if (runStateOf(c) != rs) continue retry; } } boolean workerStarted = false; boolean workerAdded = false; Worker w = null; try { //Worker实现了runnale接口,有两个属性, //firstTask 创建worker对象时待执行的第一个任务 //thread 在构建一个Woker对象时,会使用getThreadFactory().newThread(this);赋值给thread w = new Worker(firstTask); //此时线程对象还没有启动 final Thread t = w.thread; if (t != null) { final ReentrantLock mainLock = this.mainLock; mainLock.lock(); try { // 重新检查锁状态. int rs = runStateOf(ctl.get()); //如果线程池处于运行状态(< SHUTDOWN) //或者(线程池处于SHUTDOWN并且当前woker线程没有自己的第一个任务) //设置workerAdded为true,表示下面步骤启动线程 if (rs < SHUTDOWN || (rs == SHUTDOWN && firstTask == null)) { //检查线程是否启动,启动则抛异常 if (t.isAlive()) 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; }
3、继续查看Worker类结构
/** * 1、Worker继承了AbstractQueuedSynchronizer 因此也具备了AQS的特征 * 2、Worker实现了Runnable接口,因此Woker也是 * 3、AQS具备的特征:阻塞等待队列、共享/独占、公平/非公平、可重入、允许中断 */ private final class Worker extends AbstractQueuedSynchronizer implements Runnable { final Thread thread; Runnable firstTask; volatile long completedTasks; /** * @param firstTask 创建worker并执行的第一个任务 */ Worker(Runnable firstTask) { setState(-1); this.firstTask = firstTask; //***************************************************************************************** //当执行woker的thread.start()方法时,本质启动时执行的thread里run方法,而此时的参数是this,也就是Worker的run方法 //***************************************************************************************** this.thread = getThreadFactory().newThread(this); } //***************************************************************************************** //当执行run方法时,最终调用的是ThreadPoolExecutor#runWorker的方法 //***************************************************************************************** public void run() { runWorker(this); } protected boolean isHeldExclusively() { return getState() != 0; } protected boolean tryAcquire(int unused) { if (compareAndSetState(0, 1)) { setExclusiveOwnerThread(Thread.currentThread()); return true; } return false; } protected boolean tryRelease(int unused) { setExclusiveOwnerThread(null); setState(0); return true; } public void lock() { acquire(1); } public boolean tryLock() { return tryAcquire(1); } public void unlock() { release(1); } public boolean isLocked() { return isHeldExclusively(); } }
4、继续查看runWorker和getTask方法
/** * worker的thread线程启动后,本质是执行的thread里的run方法,也就是ThreadPoolExecutor#runWorker方法 * @param w the worker */ final void runWorker(Worker w) { Thread wt = Thread.currentThread(); Runnable task = w.firstTask; w.firstTask = null; w.unlock(); // allow interrupts boolean completedAbruptly = true; try { //循环获取task任务,当队列中不存在任务时,则阻塞当前线程 while (task != null || (task = getTask()) != null) { w.lock(); if ((runStateAtLeast(ctl.get(), STOP) || (Thread.interrupted() && runStateAtLeast(ctl.get(), STOP))) && !wt.isInterrupted()) wt.interrupt(); try { beforeExecute(wt, task); Throwable thrown = null; try { task.run(); } catch (RuntimeException x) { thrown = x; throw x; } catch (Error x) { thrown = x; throw x; } catch (Throwable x) { thrown = x; throw new Error(x); } finally { afterExecute(task, thrown); } } finally { task = null; w.completedTasks++; w.unlock(); } } completedAbruptly = false; } finally { //当线程出现异常时,则工作线程退出 processWorkerExit(w, completedAbruptly); } } /** * 获取到任务则执行,获取不到任务则阻塞,具体通过workQueue.take()实现 */ private Runnable getTask() { boolean timedOut = false; for (;;) { int c = ctl.get(); int rs = runStateOf(c); // Check if queue empty only if necessary. if (rs >= SHUTDOWN && (rs >= STOP || workQueue.isEmpty())) { decrementWorkerCount(); return null; } int wc = workerCountOf(c); // Are workers subject to culling? boolean timed = allowCoreThreadTimeOut || wc > corePoolSize; if ((wc > maximumPoolSize || (timed && timedOut)) && (wc > 1 || workQueue.isEmpty())) { if (compareAndDecrementWorkerCount(c)) return null; continue; } try { Runnable r = timed ? workQueue.poll(keepAliveTime, TimeUnit.NANOSECONDS) : workQueue.take(); if (r != null) return r; timedOut = true; } catch (InterruptedException retry) { timedOut = false; } } }
提问:
a、假如最大线程数为3,核心线程数为2,设置的非核心线程的最大存活时间为30秒,阻塞队列为1,那么线程池里的线程数变为2的时机是什么时候
首先我们要查看Worker里的getTask逻辑,此时总数3个线程,核心线程为2,任务队列为空,此时三个worker线程中就有一个getTask()会返回null,那么此时runWorker跳出循环执行finally里的 processWorkerExit(w, completedAbruptly)退出逻辑。
private Runnable getTask() { boolean timedOut = false; // Did the last poll() time out? for (;;) { int c = ctl.get(); int rs = runStateOf(c); if (rs >= SHUTDOWN && (rs >= STOP || workQueue.isEmpty())) { decrementWorkerCount(); return null; } int wc = workerCountOf(c); // allowCoreThreadTimeOut默认为false,表示保留核心线程数,为true,表示线程池中的所有线程都可以被回收掉 // ==1==此时总线程数为3核心线程数为2,timed为true // 注意:当总线程数等于核心线程数时,timed为false boolean timed = allowCoreThreadTimeOut || wc > corePoolSize; //==3== //timed 和 timedOut都为true并且任务队列为空 //则执行cas,执行成功线程数c-1,此时getTask就会返回null,执行cas失败则继续循环获取 if ((wc > maximumPoolSize || (timed && timedOut)) && (wc > 1 || workQueue.isEmpty())) { if (compareAndDecrementWorkerCount(c)) return null; continue; } try { //==2== //timed为true执行workQueue.poll逻辑,如果此时队列为空,就会阻塞keepAliveTime时间 //keepAliveTime时间一到,就会返回null,如果r为null则timedOut = true; //注意:timed为false,则执行workQueue.take()阻塞当前线程 Runnable r = timed ? workQueue.poll(keepAliveTime, TimeUnit.NANOSECONDS) : workQueue.take(); if (r != null) return r; timedOut = true; } catch (InterruptedException retry) { timedOut = false; } } }
private void processWorkerExit(Worker w, boolean completedAbruptly) { if (completedAbruptly) // If abrupt, then workerCount wasn't adjusted decrementWorkerCount(); final ReentrantLock mainLock = this.mainLock; mainLock.lock(); try { completedTaskCount += w.completedTasks; //此时从workers集合中移除对w的引用,等待GC回收 workers.remove(w); } finally { mainLock.unlock(); } tryTerminate(); int c = ctl.get(); if (runStateLessThan(c, STOP)) { if (!completedAbruptly) { int min = allowCoreThreadTimeOut ? 0 : corePoolSize; if (min == 0 && ! workQueue.isEmpty()) min = 1; if (workerCountOf(c) >= min) return; // replacement not needed } addWorker(null, false); } }
5、shutdown和shutdownNow
5.1、shutdown
a、shutdown:cas更新SHUTDOWN状态
//advanceRunState(SHUTDOWN); private void advanceRunState(int targetState) { for (;;) { //获取当前ctl值 int c = ctl.get(); //1.如果状态大于等于SHUTDOWN,也就是SHUTDOWN或者STOP,则break跳出循环 //2.cas更新SHUTDOWN状态 if (runStateAtLeast(c, targetState) || ctl.compareAndSet(c, ctlOf(targetState, workerCountOf(c)))) break; } }
b、shutdown:中断所有空闲线程
//private void interruptIdleWorkers() { // interruptIdleWorkers(false); //} private void interruptIdleWorkers(boolean onlyOne) { final ReentrantLock mainLock = this.mainLock; //加锁,保证对workers集合的操作是安全的 mainLock.lock(); try { for (Worker w : workers) { Thread t = w.thread; //!t.isInterrupted()如果线程未被中断过(不会清除中断标志) //w.tryLock()如果加锁成功,证明工作线程是空闲的 if (!t.isInterrupted() && w.tryLock()) { try { //中断线程 t.interrupt(); } catch (SecurityException ignore) { } finally { w.unlock(); } } //onlyOne如果为true,则只中断第一个空闲线程就跳出循环 if (onlyOne) break; } } finally { mainLock.unlock(); } }
c、shutdown:拒绝所有新增任务
public void execute(Runnable command) { ... if (isRunning(c) && workQueue.offer(command)) { int recheck = ctl.get(); //再次线程池不是RUNNING状态,从阻塞队列中把刚加入的任务移除 if (! isRunning(recheck) && remove(command)) //移除任务成功后,执行拒绝策略 reject(command); ... } ... }
5.2、shutdownNow
a、shutdownNow:cas更新STOP状态
advanceRunState(STOP); private void advanceRunState(int targetState) { for (;;) { int c = ctl.get(); //如果状态大于等于STOP,则break跳出循环 //cas更新线程池状态为STOP if (runStateAtLeast(c, targetState) || ctl.compareAndSet(c, ctlOf(targetState, workerCountOf(c)))) break; } }
b、shutdownNow:中断所有线程
interruptWorkers(); private void interruptWorkers() { final ReentrantLock mainLock = this.mainLock; //加锁,保证对worker集合的操作只有一个线程 mainLock.lock(); try { for (Worker w : workers) w.interruptIfStarted(); } finally { mainLock.unlock(); } } void interruptIfStarted() { Thread t; //getState() >= 0 确保Worker已经初始化完成,在runWorker中会把state更新为0或1 /** * final void runWorker(Worker w) { * ... * // tryRelease重写unlock()方法,将state状态设置为0 * w.unlock(); // allow interrupts * boolean completedAbruptly = true; * try { * while (task != null || (task = getTask()) != null) { * //lock状态设置为1 * w.lock(); * ... * } finally { * task = null; * w.completedTasks++; * w.unlock(); * } * } * completedAbruptly = alse; * } finally { * processWorkerExit(w, completedAbr tly); * } * } */ //!t.isInterrupted() Worker里线程未被中断 if (getState() >= 0 && (t = thread) != null && !t.isInterrupted()) { try { t.interrupt(); } catch (SecurityException ignore) { } } }
c、shutdownNow:拒绝所有任务
public void execute(Runnable command) { ... if (isRunning(c) && workQueue.offer(command)) { int recheck = ctl.get(); //再次线程池不是RUNNING状态,从阻塞队列中把刚加入的任务移除 if (! isRunning(recheck) && remove(command)) //移除任务成功后,执行拒绝策略 reject(command); ... } // 线程池状态为SHUTDOWN,并且队列为空,则拒绝创建线程,执行任务 // 线程池状态为STOP,不管队列是否为空,都拒绝创建线程,执行任务 else if (!addWorker(command, false)) reject(command); } private boolean addWorker(Runnable firstTask, boolean core) { retry: for (;;) { int c = ctl.get(); int rs = runStateOf(c); // 线程池状态为SHUTDOWN,并且队列为空,则拒绝创建线程 // 线程池状态为STOP,不管队列是否为空,都拒绝创建线程 if (rs >= SHUTDOWN && ! (rs == SHUTDOWN && firstTask == null && ! workQueue.isEmpty())) return false; } ... }
6、线程退出
a、从阻塞队列中获取任务为null,从workers移除当前线程
private Runnable getTask() { boolean timedOut = false; // Did the last poll() time out? for (;;) { int c = ctl.get(); int rs = runStateOf(c); // 如果线程池状态为SHUTDOWN 并且 队列为空,getTask()直接返回null // 如果线程池状态为STOP,getTask()直接返回null if (rs >= SHUTDOWN && (rs >= STOP || workQueue.isEmpty())) { //线程数量减1 decrementWorkerCount(); return null; } int wc = workerCountOf(c); // 线程数量大于核心线程数,此时timed为true boolean timed = allowCoreThreadTimeOut || wc > corePoolSize; //当timed和timedOut都为true,并且(线程数大于1 或队列为空),则执行线程数cas减1,并且返回null退出循环 if ((wc > maximumPoolSize || (timed && timedOut)) && (wc > 1 || workQueue.isEmpty())) { if (compareAndDecrementWorkerCount(c)) return null; continue; } try { //要么超时阻塞,要么无时限阻塞 Runnable r = timed ? workQueue.poll(keepAliveTime, TimeUnit.NANOSECONDS) : workQueue.take(); //没有超时,在阻塞期间获取到了任务 if (r != null) return r; //超时了,重新进入循环,上面的代码会判断出来当前线程阻塞超时了,直接返回null timedOut = true; } catch (InterruptedException retry) { timedOut = false; } } } //getTask()为null,completedAbruptly = false //processWorkerExit(w, completedAbruptly); private void processWorkerExit(Worker w, boolean completedAbruptly) { ... final ReentrantLock mainLock = this.mainLock; mainLock.lock(); try { completedTaskCount += w.completedTasks; workers.remove(w); } finally { mainLock.unlock(); } ... int c = ctl.get(); //线程池小于STOP状态 if (runStateLessThan(c, STOP)) { if (!completedAbruptly) { //allowCoreThreadTimeOut为true,并且阻塞队列不为空,那么min为1(表示至少保留1个线程处理任务) //allowCoreThreadTimeOut为false,那么min为corePoolSize,表示至少保留corePoolSize个工作线程 int min = allowCoreThreadTimeOut ? 0 : corePoolSize; if (min == 0 && ! workQueue.isEmpty()) min = 1; //如果工作线程大于等于min,则符合保留的最小线程数,直接return,不会调用下面的addWorker新开一个线程了 if (workerCountOf(c) >= min) return; } addWorker(null, false); } }
b、执行任务异常,当前线程会被移除,再重新添加一个新线程替补因异常退出的线程
final void runWorker(Worker w) { Thread wt = Thread.currentThread(); Runnable task = w.firstTask; w.firstTask = null; w.unlock(); // allow interrupts boolean completedAbruptly = true; try { while (task != null || (task = getTask()) != null) { ... } completedAbruptly = false; } finally { //抛出异常,completedAbruptly此时为true,最终执行退出,并新增一个非核心线程 processWorkerExit(w, completedAbruptly); } } private void processWorkerExit(Worker w, boolean completedAbruptly) { //工作线程数量减1 if (completedAbruptly) decrementWorkerCount(); final ReentrantLock mainLock = this.mainLock; mainLock.lock(); try { completedTaskCount += w.completedTasks; workers.remove(w); } finally { mainLock.unlock(); } ... int c = ctl.get(); //如果线程池状态小于STOP,即RUNNING或SHUTDOWN状态,则需要添加一个非核心线程 if (runStateLessThan(c, STOP)) { ... //添加一个非核心线程 addWorker(null, false); } }
扩展:我们知道线程池执行任务逻辑:执行任务,核心线程创建完成后,剩余的任务就会执行入队逻辑,队列满后,再创建非核心线程,那么我怎么才能实现创建线程达到最大数量后,才执行入队逻辑,怎么实现。
这个逻辑tomcat的线程池已经实现了,也就是自定义一个阻塞队列TaskQueue,在offer入队前,判断允许最大线程数是否等于worker数量,是则入队,否则返回false,具体实现如下:
class TaskQueue extends LinkedBlockingQueue<Runnable> { private ThreadPoolExecutor parent; public void setParent(ThreadPoolExecutor parent) { this.parent = parent; } @Override public boolean offer(Runnable o) { // 若未绑定线程池,直接入队(避免逻辑错误) if (parent == null) { return super.offer(o); } // 关键逻辑:线程数 < 最大线程数时,拒绝入队(迫使线程池创建新线程) if (parent.getPoolSize() < parent.getMaximumPoolSize()) { return false; } // 线程数已达最大,正常入队 return super.offer(o); } } public class JdkWithTaskQueueDemo { public static void main(String[] args) { // 1. 创建TaskQueue并绑定线程池 TaskQueue queue = new TaskQueue(); // 2. 创建JDK线程池(核心2,最大5,队列容量10) ThreadPoolExecutor executor = new ThreadPoolExecutor( 2, 5, 60, TimeUnit.SECONDS, queue, new ThreadFactory() { // 自定义线程工厂(方便打印线程名) private final AtomicInteger count = new AtomicInteger(1); @Override public Thread newThread(Runnable r) { return new Thread(r, "worker-" + count.getAndIncrement()); } }, new ThreadPoolExecutor.AbortPolicy() ); // 3. 绑定线程池到队列(必须步骤!否则TaskQueue不生效) queue.setParent(executor); // 测试:提交10个任务 for (int i = 0; i < 10; i++) { int taskId = i; executor.execute(() -> { try { Thread.sleep(1000); // 模拟任务执行 System.out.println("任务" + taskId + "执行,线程:" + Thread.currentThread().getName()); } catch (InterruptedException e) { e.printStackTrace(); } }); } executor.shutdown(); } }

浙公网安备 33010602011771号