ThreadPoolExcutor源码分析
来源:互联网 发布:ubuntu 进入boot 编辑:程序博客网 时间:2024/06/04 21:30
核心接口: Executor
public interface Executor { /** * Executes the given command at some time in the future. The command * may execute in a new thread, in a pooled thread, or in the calling * thread, at the discretion of the {@code Executor} implementation. * * @param command the runnable task * @throws RejectedExecutionException if this task cannot be * accepted for execution * @throws NullPointerException if command is null */ void execute(Runnable command);}
execute
方法抽象为对任务(Runnable接口)的执行。ExecutorService
接口在Executor
的基础上提供了对任务执行的生命周期的管理,主要是submit
和shutdown
方法。
public interface ExecutorService extends Executor { /** * Initiates an orderly shutdown in which previously submitted * tasks are executed, but no new tasks will be accepted. * Invocation has no additional effect if already shut down. * * <p>This method does not wait for previously submitted tasks to * complete execution. Use {@link #awaitTermination awaitTermination} * to do that. * * @throws SecurityException if a security manager exists and * shutting down this ExecutorService may manipulate * threads that the caller is not permitted to modify * because it does not hold {@link * java.lang.RuntimePermission}{@code ("modifyThread")}, * or the security manager's {@code checkAccess} method * denies access. */ void shutdown(); /** * Attempts to stop all actively executing tasks, halts the * processing of waiting tasks, and returns a list of the tasks * that were awaiting execution. * * <p>This method does not wait for actively executing tasks to * terminate. Use {@link #awaitTermination awaitTermination} to * do that. * * <p>There are no guarantees beyond best-effort attempts to stop * processing actively executing tasks. For example, typical * implementations will cancel via {@link Thread#interrupt}, so any * task that fails to respond to interrupts may never terminate. * * @return list of tasks that never commenced execution * @throws SecurityException if a security manager exists and * shutting down this ExecutorService may manipulate * threads that the caller is not permitted to modify * because it does not hold {@link * java.lang.RuntimePermission}{@code ("modifyThread")}, * or the security manager's {@code checkAccess} method * denies access. */ List<Runnable> shutdownNow(); /** * Returns {@code true} if this executor has been shut down. * * @return {@code true} if this executor has been shut down */ boolean isShutdown(); /** * Returns {@code true} if all tasks have completed following shut down. * Note that {@code isTerminated} is never {@code true} unless * either {@code shutdown} or {@code shutdownNow} was called first. * * @return {@code true} if all tasks have completed following shut down */ boolean isTerminated(); /** * Blocks until all tasks have completed execution after a shutdown * request, or the timeout occurs, or the current thread is * interrupted, whichever happens first. * * @param timeout the maximum time to wait * @param unit the time unit of the timeout argument * @return {@code true} if this executor terminated and * {@code false} if the timeout elapsed before termination * @throws InterruptedException if interrupted while waiting */ boolean awaitTermination(long timeout, TimeUnit unit) throws InterruptedException; /** * Submits a value-returning task for execution and returns a * Future representing the pending results of the task. The * Future's {@code get} method will return the task's result upon * successful completion. * * <p> * If you would like to immediately block waiting * for a task, you can use constructions of the form * {@code result = exec.submit(aCallable).get();} * * <p>Note: The {@link Executors} class includes a set of methods * that can convert some other common closure-like objects, * for example, {@link java.security.PrivilegedAction} to * {@link Callable} form so they can be submitted. * * @param task the task to submit * @param <T> the type of the task's result * @return a Future representing pending completion of the task * @throws RejectedExecutionException if the task cannot be * scheduled for execution * @throws NullPointerException if the task is null */ <T> Future<T> submit(Callable<T> task); /** * Submits a Runnable task for execution and returns a Future * representing that task. The Future's {@code get} method will * return the given result upon successful completion. * * @param task the task to submit * @param result the result to return * @param <T> the type of the result * @return a Future representing pending completion of the task * @throws RejectedExecutionException if the task cannot be * scheduled for execution * @throws NullPointerException if the task is null */ <T> Future<T> submit(Runnable task, T result); /** * Submits a Runnable task for execution and returns a Future * representing that task. The Future's {@code get} method will * return {@code null} upon <em>successful</em> completion. * * @param task the task to submit * @return a Future representing pending completion of the task * @throws RejectedExecutionException if the task cannot be * scheduled for execution * @throws NullPointerException if the task is null */ Future<?> submit(Runnable task); /** * Executes the given tasks, returning a list of Futures holding * their status and results when all complete. * {@link Future#isDone} is {@code true} for each * element of the returned list. * Note that a <em>completed</em> task could have * terminated either normally or by throwing an exception. * The results of this method are undefined if the given * collection is modified while this operation is in progress. * * @param tasks the collection of tasks * @param <T> the type of the values returned from the tasks * @return a list of Futures representing the tasks, in the same * sequential order as produced by the iterator for the * given task list, each of which has completed * @throws InterruptedException if interrupted while waiting, in * which case unfinished tasks are cancelled * @throws NullPointerException if tasks or any of its elements are {@code null} * @throws RejectedExecutionException if any task cannot be * scheduled for execution */ <T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks) throws InterruptedException; /** * Executes the given tasks, returning a list of Futures holding * their status and results * when all complete or the timeout expires, whichever happens first. * {@link Future#isDone} is {@code true} for each * element of the returned list. * Upon return, tasks that have not completed are cancelled. * Note that a <em>completed</em> task could have * terminated either normally or by throwing an exception. * The results of this method are undefined if the given * collection is modified while this operation is in progress. * * @param tasks the collection of tasks * @param timeout the maximum time to wait * @param unit the time unit of the timeout argument * @param <T> the type of the values returned from the tasks * @return a list of Futures representing the tasks, in the same * sequential order as produced by the iterator for the * given task list. If the operation did not time out, * each task will have completed. If it did time out, some * of these tasks will not have completed. * @throws InterruptedException if interrupted while waiting, in * which case unfinished tasks are cancelled * @throws NullPointerException if tasks, any of its elements, or * unit are {@code null} * @throws RejectedExecutionException if any task cannot be scheduled * for execution */ <T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks, long timeout, TimeUnit unit) throws InterruptedException; /** * Executes the given tasks, returning the result * of one that has completed successfully (i.e., without throwing * an exception), if any do. Upon normal or exceptional return, * tasks that have not completed are cancelled. * The results of this method are undefined if the given * collection is modified while this operation is in progress. * * @param tasks the collection of tasks * @param <T> the type of the values returned from the tasks * @return the result returned by one of the tasks * @throws InterruptedException if interrupted while waiting * @throws NullPointerException if tasks or any element task * subject to execution is {@code null} * @throws IllegalArgumentException if tasks is empty * @throws ExecutionException if no task successfully completes * @throws RejectedExecutionException if tasks cannot be scheduled * for execution */ <T> T invokeAny(Collection<? extends Callable<T>> tasks) throws InterruptedException, ExecutionException; /** * Executes the given tasks, returning the result * of one that has completed successfully (i.e., without throwing * an exception), if any do before the given timeout elapses. * Upon normal or exceptional return, tasks that have not * completed are cancelled. * The results of this method are undefined if the given * collection is modified while this operation is in progress. * * @param tasks the collection of tasks * @param timeout the maximum time to wait * @param unit the time unit of the timeout argument * @param <T> the type of the values returned from the tasks * @return the result returned by one of the tasks * @throws InterruptedException if interrupted while waiting * @throws NullPointerException if tasks, or unit, or any element * task subject to execution is {@code null} * @throws TimeoutException if the given timeout elapses before * any task successfully completes * @throws ExecutionException if no task successfully completes * @throws RejectedExecutionException if tasks cannot be scheduled * for execution */ <T> T invokeAny(Collection<? extends Callable<T>> tasks, long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException;}
AbstractExecutorService
对ExecutorService
一些方法做了默认的实现,主要是submit和invoke方法。真正的任务执行 的Executor接口execute
方法是由子类实现,就是ThreadPoolExecutor
,它实现了基于线程池的任务执行框架。
1.ctl
private final AtomicInteger ctl = new AtomicInteger(ctlOf(RUNNING, 0));
这个变量是整个类的核心,AtomicInteger
保证了对这个变量的操作是原子的,通过巧妙的操作,ThreadPoolExecutor用这一个变量保存了两个内容:
- 所有有效线程的数量
- 各个线程的状态(runState)
低29位存线程数,高3位存runState
,这样runState有5个值:
- RUNNING:-536870912
- SHUTDOWN:0
- STOP:536870912
- TIDYING:1073741824: 所有的任务都已经停止,workerCount为0,线程变成TIDYING状态会运行terminate()
- TERMINATED:1610612736:terminated()已经完成
线程池中各个状态间的转换比较复杂,主要记住下面内容就可以了:
- RUNNING状态:线程池正常运行,可以接受新的任务并处理队列中的任务;
- SHUTDOWN状态:不再接受新的任务,但是会执行队列中的任务;
- STOP状态:不再接受新任务,不处理队列中的任务
围绕ctl变量有一些操作,了解这些方法是看懂后面一些晦涩代码的基础:
/** * 这个方法用于取出runState的值 因为CAPACITY值为:00011111111111111111111111111111 * ~为按位取反操作,则~CAPACITY值为:11100000000000000000000000000000 * 再同参数做&操作,就将低29位置0了,而高3位还是保持原先的值,也就是runState的值 * * @param c * 该参数为存储runState和workerCount的int值 * @return runState的值 */private static int runStateOf(int c) { return c & ~CAPACITY;}/** * 这个方法用于取出workerCount的值 * 因为CAPACITY值为:00011111111111111111111111111111,所以&操作将参数的高3位置0了 * 保留参数的低29位,也就是workerCount的值 * * @param c * ctl, 存储runState和workerCount的int值 * @return workerCount的值 */private static int workerCountOf(int c) { return c & CAPACITY;}/** * 将runState和workerCount存到同一个int中 * “|”运算的意思是,假设rs的值是101000,wc的值是000111,则他们位或运算的值为101111 * * @param rs * runState移位过后的值,负责填充返回值的高3位 * @param wc * workerCount移位过后的值,负责填充返回值的低29位 * @return 两者或运算过后的值 */private static int ctlOf(int rs, int wc) { return rs | wc;}// 只有RUNNING状态会小于0private static boolean isRunning(int c) { return c < SHUTDOWN;}
2.CorePoolSize
核心线程池大小,活动线程小于corePoolSize则直接创建,大于等于则先加到workQueue中,队列满了才创建新的线程。
3.KeepAliveTime
线程从队列中获取任务的超时时间,也就是说如果线程空闲超过这个时间就会终止。
4.Work
/** * Class Worker mainly maintains interrupt control state for * threads running tasks, along with other minor bookkeeping. * This class opportunistically extends AbstractQueuedSynchronizer * to simplify acquiring and releasing a lock surrounding each * task execution. This protects against interrupts that are * intended to wake up a worker thread waiting for a task from * instead interrupting a task being run. We implement a simple * non-reentrant mutual exclusion lock rather than use * ReentrantLock because we do not want worker tasks to be able to * reacquire the lock when they invoke pool control methods like * setCorePoolSize. Additionally, to suppress interrupts until * the thread actually starts running tasks, we initialize lock * state to a negative value, and clear it upon start (in * runWorker). */private final class Worker extends AbstractQueuedSynchronizer implements Runnable { /** * This class will never be serialized, but we provide a * serialVersionUID to suppress a javac warning. */ private static final long serialVersionUID = 6138294804551838833L; /** Thread this worker is running in. Null if factory fails. */ final Thread thread; /** Initial task to run. Possibly null. */ Runnable firstTask; /** Per-thread task counter */ volatile long completedTasks; /** * Creates with given first task and thread from ThreadFactory. * @param firstTask the first task (null if none) */ Worker(Runnable firstTask) { setState(-1); // inhibit interrupts until runWorker this.firstTask = firstTask; this.thread = getThreadFactory().newThread(this); } /** Delegates main run loop to outer runWorker */ public void run() { runWorker(this); } // Lock methods // // The value 0 represents the unlocked state. // The value 1 represents the locked state. protected boolean isHeldExclusively() { return getState() != 0; }// state只有0和1,互斥 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(); } void interruptIfStarted() { Thread t; if (getState() >= 0 && (t = thread) != null && !t.isInterrupted()) { try { t.interrupt(); } catch (SecurityException ignore) { } } } }
继承于AbstractQueuedSynchronizer类,任务执行时获取释放锁,这样可以防止中断,目的在于唤醒线程,而不是中断正在执行的任务。
用AQS框架实现了一个简单的非重入的互斥锁, 实现互斥锁主要目的是为了中断的时候判断线程是在空闲还是运行,可以看后面shutdown
和shutdownNow
方法的分析(tryAcquire和tryRelease)。
之所以不用ReentrantLock是为了避免任务执行的代码中修改线程池的变量,如setCorePoolSize
,因为ReentrantLock是可重入的。
5.Execute
execute
方法主要三个步骤:
- 活动线程小于corePoolSize的时候创建新的线程;
- 活动线程大于corePoolSize时都是先加入到任务队列当中;
- 任务队列满了再去启动新的线程,如果线程数达到最大值就拒绝任务。
/** * Executes the given task sometime in the future. The task * may execute in a new thread or in an existing pooled thread. * * If the task cannot be submitted for execution, either because this * executor has been shutdown or because its capacity has been reached, * the task is handled by the current {@code RejectedExecutionHandler}. * * @param command the task to execute * @throws RejectedExecutionException at discretion of * {@code RejectedExecutionHandler}, if the task * cannot be accepted for execution * @throws NullPointerException if {@code command} is null */ public void execute(Runnable command) { 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. */ int c = ctl.get(); // 活动线程数 < corePoolSize if (workerCountOf(c) < corePoolSize) { // 直接启动新的线程。第二个参数true:addWorker中会重新检查workerCount是否小于corePoolSize if (addWorker(command, true)) // 添加成功返回 return; c = ctl.get(); } // 活动线程数 >= corePoolSize // runState为RUNNING && 队列未满 if (isRunning(c) && workQueue.offer(command)) { int recheck = ctl.get(); // double check // 非RUNNING状态 则从workQueue中移除任务并拒绝 if (! isRunning(recheck) && remove(command)) reject(command);// 采用线程池指定的策略拒绝任务 // 线程池处于RUNNING状态 || 线程池处于非RUNNING状态但是任务移除失败 else if (workerCountOf(recheck) == 0) // 这行代码是为了SHUTDOWN状态下没有活动线程了,但是队列里还有任务没执行这种特殊情况。 // 添加一个null任务是因为SHUTDOWN状态下,线程池不再接受新任务 addWorker(null, false); // 两种情况: // 1.非RUNNING状态拒绝新的任务 // 2.队列满了启动新的线程失败(workCount > maximumPoolSize) } else if (!addWorker(command, false)) reject(command); }
其中比较难理解的应该是
addWorker(null, false);
这一行,这要结合addWorker一起来看。 主要目的是防止HUTDOWN状态下没有活动线程了,但是队列里还有任务没执行这种特殊情况。/* * Methods for creating, running and cleaning up after workers */ /** * Checks if a new worker can be added with respect to current * pool state and the given bound (either core or maximum). If so, * the worker count is adjusted accordingly, and, if possible, a * new worker is created and started, running firstTask as its * first task. This method returns false if the pool is stopped or * eligible to shut down. It also returns false if the thread * factory fails to create a thread when asked. If the thread * creation fails, either due to the thread factory returning * null, or due to an exception (typically OutOfMemoryError in * Thread.start()), we roll back cleanly. * * @param firstTask the task the new thread should run first (or * null if none). Workers are created with an initial first task * (in method execute()) to bypass queuing when there are fewer * than corePoolSize threads (in which case we always start one), * or when the queue is full (in which case we must bypass queue). * Initially idle threads are usually created via * prestartCoreThread or to replace other dying workers. * * @param core if true use corePoolSize as bound, else * maximumPoolSize. (A boolean indicator is used here rather than a * value to ensure reads of fresh values after checking other pool * state). * @return true if successful */ private boolean addWorker(Runnable firstTask, boolean core) { retry: for (;;) { int c = ctl.get(); int rs = runStateOf(c);//当前线程池状态 // Check if queue empty only if necessary. // 这条语句等价:rs >= SHUTDOWN && (rs != SHUTDOWN || firstTask != null || // workQueue.isEmpty()) // 满足下列调价则直接返回false,线程创建失败: // rs > SHUTDOWN:STOP || TIDYING || TERMINATED 此时不再接受新的任务,且所有任务执行结束 // rs = SHUTDOWN:firtTask != null 此时不再接受任务,但是仍然会执行队列中的任务 // rs = SHUTDOWN:firtTask == null见execute方法的addWorker(null, // false),任务为null && 队列为空 // 最后一种情况也就是说SHUTDONW状态下,如果队列不为空还得接着往下执行,为什么?add一个null任务目的到底是什么? // 看execute方法只有workCount==0的时候firstTask才会为null结合这里的条件就是线程池SHUTDOWN了不再接受新任务 // 但是此时队列不为空,那么还得创建线程把任务给执行完才行。 if (rs >= SHUTDOWN && ! (rs == SHUTDOWN && firstTask == null && ! workQueue.isEmpty())) return false; // 走到这的情形: // 1.线程池状态为RUNNING // 2.SHUTDOWN状态,但队列中还有任务需要执行 for (;;) { int wc = workerCountOf(c); if (wc >= CAPACITY || wc >= (core ? corePoolSize : maximumPoolSize)) return false; if (compareAndIncrementWorkerCount(c))// 原子操作递增workCount break retry;// 操作成功跳出的重试的循环 c = ctl.get(); // Re-read ctl if (runStateOf(c) != rs)// 如果线程池的状态发生变化则重试 continue retry; // else CAS failed due to workerCount change; retry inner loop } }// wokerCount递增成功 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;// 并发的访问线程池workers对象必须加锁 mainLock.lock(); try { // Recheck while holding lock. // Back out on ThreadFactory failure or if // shut down before lock acquired. int rs = runStateOf(ctl.get()); // RUNNING状态 || SHUTDONW状态下清理队列中剩余的任务 if (rs < SHUTDOWN || (rs == SHUTDOWN && firstTask == null)) { if (t.isAlive()) // precheck that t is startable throw new IllegalThreadStateException();// 将新启动的线程添加到线程池中 workers.add(w);// 更新largestPoolSize int s = workers.size(); if (s > largestPoolSize) largestPoolSize = s; workerAdded = true; } } finally { mainLock.unlock(); }// 启动新添加的线程,这个线程首先执行firstTask,然后不停的从队列中取任务执行 // 当等待keepAlieTime还没有任务执行则该线程结束。见runWoker和getTask方法的代码。 if (workerAdded) { t.start();//最终执行的是ThreadPoolExecutor的runWoker方法 workerStarted = true; } } } finally { // 线程启动失败,则从wokers中移除w并递减wokerCount if (! workerStarted) // 递减wokerCount会触发tryTerminate方法 addWorkerFailed(w); } return workerStarted; }
7. runWorker
任务添加成功后实际执行的是runWorker
这个方法,这个方法非常重要,简单来说它做的就是:
- 第一次启动会执行初始化传进来的任务firstTask;
- 然后会从workQueue中取任务执行,如果队列为空则等待keepAliveTime这么长时间。
/** * Main worker run loop. Repeatedly gets tasks from queue and * executes them, while coping with a number of issues: * * 1. We may start out with an initial task, in which case we * don't need to get the first one. Otherwise, as long as pool is * running, we get tasks from getTask. If it returns null then the * worker exits due to changed pool state or configuration * parameters. Other exits result from exception throws in * external code, in which case completedAbruptly holds, which * usually leads processWorkerExit to replace this thread. * * 2. Before running any task, the lock is acquired to prevent * other pool interrupts while the task is executing, and then we * ensure that unless pool is stopping, this thread does not have * its interrupt set. * * 3. Each task run is preceded by a call to beforeExecute, which * might throw an exception, in which case we cause thread to die * (breaking loop with completedAbruptly true) without processing * the task. * * 4. Assuming beforeExecute completes normally, we run the task, * gathering any of its thrown exceptions to send to afterExecute. * We separately handle RuntimeException, Error (both of which the * specs guarantee that we trap) and arbitrary Throwables. * Because we cannot rethrow Throwables within Runnable.run, we * wrap them within Errors on the way out (to the thread's * UncaughtExceptionHandler). Any thrown exception also * conservatively causes thread to die. * * 5. After task.run completes, we call afterExecute, which may * also throw an exception, which will also cause thread to * die. According to JLS Sec 14.20, this exception is the one that * will be in effect even if task.run throws. * * The net effect of the exception mechanics is that afterExecute * and the thread's UncaughtExceptionHandler have as accurate * information as we can provide about any problems encountered by * user code. * * @param w the worker */ final void runWorker(Worker w) { Thread wt = Thread.currentThread(); Runnable task = w.firstTask; w.firstTask = null;// Worker的构造函数中抑制了线程中断setState(-1),所以这里需要unlock从而允许中断 w.unlock(); // allow interrupts// 用于标识是否异常终止,finally中processWorkerExit的方法会有不同逻辑 // 为true的情况:1.执行任务抛出异常;2.被中断。 boolean completedAbruptly = true; try {// 如果getTask返回null那么getTask中会将workerCount递减,如果异常了这个递减操作会在processWorkerExit中处理 while (task != null || (task = getTask()) != null) { w.lock(); // If pool is stopping, ensure thread is interrupted; // if not, ensure thread is not interrupted. This // requires a recheck in second case to deal with // shutdownNow race while clearing interrupt 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 {// 和beforeExecute一样,留给子类去重载 afterExecute(task, thrown); } } finally { task = null; w.completedTasks++; w.unlock(); } } completedAbruptly = false; } finally { // 结束线程的一些清理工作 processWorkerExit(w, completedAbruptly); } }
8.getTask
/** * Performs blocking or timed wait for a task, depending on * current configuration settings, or returns null if this worker * must exit because of any of: * 1. There are more than maximumPoolSize workers (due to * a call to setMaximumPoolSize). * 2. The pool is stopped. * 3. The pool is shutdown and the queue is empty. * 4. This worker timed out waiting for a task, and timed-out * workers are subject to termination (that is, * {@code allowCoreThreadTimeOut || workerCount > corePoolSize}) * both before and after the timed wait, and if the queue is * non-empty, this worker is not the last thread in the pool. * * @return task, or null if the worker must exit, in which case * workerCount is decremented */ private Runnable getTask() { boolean timedOut = false; // Did the last poll() time out? for (;;) { int c = ctl.get(); int rs = runStateOf(c); // Check if queue empty only if necessary. // 1.rs > SHUTDOWN 所以rs至少等于STOP,这时不再处理队列中的任务 // 2.rs = SHUTDOWN 所以rs>=STOP肯定不成立,这时还需要处理队列中的任务除非队列为空 // 这两种情况都会返回null让runWoker退出while循环也就是当前线程结束了,所以必须要decrement // wokerCount if (rs >= SHUTDOWN && (rs >= STOP || workQueue.isEmpty())) {// 递减workerCount值 decrementWorkerCount(); return null; } int wc = workerCountOf(c); // Are workers subject to culling? // 1.core thread允许被超时,那么超过corePoolSize的的线程必定有超时 // 2.allowCoreThreadTimeOut == false && wc > // corePoolSize时,一般都是这种情况,core thread即使空闲也不会被回收,只要超过的线程才会 boolean timed = allowCoreThreadTimeOut || wc > corePoolSize; // 从addWorker可以看到一般wc不会大于maximumPoolSize,所以更关心后面半句的情形: // 1. timedOut == false 第一次执行循环, 从队列中取出任务不为null方法返回 或者 // poll出异常了重试 // 2.timeOut == true && timed == // false:看后面的代码workerQueue.poll超时时timeOut才为true, // 并且timed要为false,这两个条件相悖不可能同时成立(既然有超时那么timed肯定为true) // 所以超时不会继续执行而是return null结束线程。(重点:线程是如何超时的???) if ((wc > maximumPoolSize || (timed && timedOut)) && (wc > 1 || workQueue.isEmpty())) { // workerCount递减,结束当前thread if (compareAndDecrementWorkerCount(c)) return null; continue; } try { // 1.以指定的超时时间从队列中取任务 // 2.core thread没有超时 Runnable r = timed ? workQueue.poll(keepAliveTime, TimeUnit.NANOSECONDS) : workQueue.take(); if (r != null) return r; timedOut = true;// 超时 } catch (InterruptedException retry) { timedOut = false;// 线程被中断重试 } } }
线程退出会执行这个方法做一些清理工作。
/** * Performs cleanup and bookkeeping for a dying worker. Called * only from worker threads. Unless completedAbruptly is set, * assumes that workerCount has already been adjusted to account * for exit. This method removes thread from worker set, and * possibly terminates the pool or replaces the worker if either * it exited due to user task exception or if fewer than * corePoolSize workers are running or queue is non-empty but * there are no workers. * * @param w the worker * @param completedAbruptly if the worker died due to user exception */ private void processWorkerExit(Worker w, boolean completedAbruptly) {// 正常的话再runWorker的getTask方法workerCount已经被减一了 if (completedAbruptly) // If abrupt, then workerCount wasn't adjusted decrementWorkerCount(); final ReentrantLock mainLock = this.mainLock; mainLock.lock(); try { // 累加线程的completedTasks completedTaskCount += w.completedTasks; // 从线程池中移除超时或者出现异常的线程 workers.remove(w); } finally { mainLock.unlock(); } // 尝试停止线程池 tryTerminate(); int c = ctl.get(); // runState为RUNNING或SHUTDOWN if (runStateLessThan(c, STOP)) { // 线程不是异常结束 if (!completedAbruptly) { // 线程池最小空闲数,允许core thread超时就是0,否则就是corePoolSize int min = allowCoreThreadTimeOut ? 0 : corePoolSize; // 如果min == 0但是队列不为空要保证有1个线程来执行队列中的任务 if (min == 0 && ! workQueue.isEmpty()) min = 1; // 线程池还不为空那就不用担心了 if (workerCountOf(c) >= min) return; // replacement not needed } // 1.线程异常退出 // 2.线程池为空,但是队列中还有任务没执行,看addWoker方法对这种情况的处理 addWorker(null, false); } }
10. TryTerminate
processWorkerExit方法中会尝试调用tryTerminate来终止线程池。这个方法在任何可能导致线程池终止的动作后执行:比如减少wokerCount或SHUTDOWN状态下从队列中移除任务。
/** * Transitions to TERMINATED state if either (SHUTDOWN and pool * and queue empty) or (STOP and pool empty). If otherwise * eligible to terminate but workerCount is nonzero, interrupts an * idle worker to ensure that shutdown signals propagate. This * method must be called following any action that might make * termination possible -- reducing worker count or removing tasks * from the queue during shutdown. The method is non-private to * allow access from ScheduledThreadPoolExecutor. */ final void tryTerminate() { for (;;) { int c = ctl.get(); // 以下状态直接返回: // 1.线程池还处于RUNNING状态 // 2.SHUTDOWN状态但是任务队列非空 // 3.runState >= TIDYING 线程池已经停止了或在停止了 if (isRunning(c) || runStateAtLeast(c, TIDYING) || (runStateOf(c) == SHUTDOWN && ! workQueue.isEmpty())) return; // 只能是以下情形会继续下面的逻辑:结束线程池。 // 1.SHUTDOWN状态,这时不再接受新任务而且任务队列也空了 // 2.STOP状态,当调用了shutdownNow方法 // workerCount不为0则还不能停止线程池,而且这时线程都处于空闲等待的状态 // 需要中断让线程“醒”过来,醒过来的线程才能继续处理shutdown的信号。 if (workerCountOf(c) != 0) { // Eligible to terminate // runWoker方法中w.unlock就是为了可以被中断,getTask方法也处理了中断。 // ONLY_ONE:这里只需要中断1个线程去处理shutdown信号就可以了。 interruptIdleWorkers(ONLY_ONE); return; } final ReentrantLock mainLock = this.mainLock; mainLock.lock(); try { // 进入TIDYING状态 if (ctl.compareAndSet(c, ctlOf(TIDYING, 0))) { try { // 子类重载:一些资源清理工作 terminated(); } finally { // TERMINATED状态 ctl.set(ctlOf(TERMINATED, 0)); // 继续awaitTermination termination.signalAll(); } return; } } finally { mainLock.unlock(); } // else retry on failed CAS } }
11.ShutDown 和ShutDownNow
shutdown这个方法会将runState置为SHUTDOWN
,会终止所有空闲的线程。
/** * Initiates an orderly shutdown in which previously submitted * tasks are executed, but no new tasks will be accepted. * Invocation has no additional effect if already shut down. * * <p>This method does not wait for previously submitted tasks to * complete execution. Use {@link #awaitTermination awaitTermination} * to do that. * * @throws SecurityException {@inheritDoc} */ public void shutdown() { final ReentrantLock mainLock = this.mainLock; mainLock.lock(); try { checkShutdownAccess(); // 线程池状态设为SHUTDOWN,如果已经至少是这个状态那么则直接返回 advanceRunState(SHUTDOWN); // 注意这里是中断所有空闲的线程:runWorker中等待的线程被中断 → 进入processWorkerExit → // tryTerminate方法中会保证队列中剩余的任务得到执行。 interruptIdleWorkers(); onShutdown(); // hook for ScheduledThreadPoolExecutor } finally { mainLock.unlock(); } tryTerminate(); }
shutdownNow方法将runState置为STOP。和shutdown方法的区别,这个方法会终止所有的线程。
/** * Attempts to stop all actively executing tasks, halts the * processing of waiting tasks, and returns a list of the tasks * that were awaiting execution. These tasks are drained (removed) * from the task queue upon return from this method. * * <p>This method does not wait for actively executing tasks to * terminate. Use {@link #awaitTermination awaitTermination} to * do that. * * <p>There are no guarantees beyond best-effort attempts to stop * processing actively executing tasks. This implementation * cancels tasks via {@link Thread#interrupt}, so any task that * fails to respond to interrupts may never terminate. * * @throws SecurityException {@inheritDoc} */ public List<Runnable> shutdownNow() { List<Runnable> tasks; final ReentrantLock mainLock = this.mainLock; mainLock.lock(); try { checkShutdownAccess(); // STOP状态:不再接受新任务且不再执行队列中的任务。 advanceRunState(STOP); // 中断所有线程 interruptWorkers(); // 返回队列中还没有被执行的任务。 tasks = drainQueue(); } finally { mainLock.unlock(); } tryTerminate(); return tasks; } public boolean isShutdown() { return ! isRunning(ctl.get()); }
主要区别在于shutdown调用的是
interruptIdleWorkers
这个方法,而shutdownNow实际调用的是Worker类的interruptIfStarted
方法:/** * Interrupts threads that might be waiting for tasks (as * indicated by not being locked) so they can check for * termination or configuration changes. Ignores * SecurityExceptions (in which case some threads may remain * uninterrupted). * * @param onlyOne If true, interrupt at most one worker. This is * called only from tryTerminate when termination is otherwise * enabled but there are still other workers. In this case, at * most one waiting worker is interrupted to propagate shutdown * signals in case all threads are currently waiting. * Interrupting any arbitrary thread ensures that newly arriving * workers since shutdown began will also eventually exit. * To guarantee eventual termination, it suffices to always * interrupt only one idle worker, but shutdown() interrupts all * idle workers so that redundant workers exit promptly, not * waiting for a straggler task to finish. */ private void interruptIdleWorkers(boolean onlyOne) { final ReentrantLock mainLock = this.mainLock; mainLock.lock(); try { for (Worker w : workers) { Thread t = w.thread; // w.tryLock能获取到锁,说明该线程没有在运行,因为runWorker中执行任务会先lock, // 因此保证了中断的肯定是空闲的线程。 if (!t.isInterrupted() && w.tryLock()) { try { t.interrupt(); } catch (SecurityException ignore) { } finally { w.unlock(); } } if (onlyOne) break; } } finally { mainLock.unlock(); } }
void interruptIfStarted() { Thread t; // 初始化时state == -1 if (getState() >= 0 && (t = thread) != null && !t.isInterrupted()) { try { t.interrupt(); } catch (SecurityException ignore) { } } }这就是前面提到的Woker类实现AQS的主要作用。
- ThreadPoolExcutor源码分析
- ThreadPoolExcutor详解
- 线程池ThreadPoolExcutor
- 安卓中使用ThreadPoolExcutor
- ThreadPoolExcutor(线程池)
- ThreadPoolExcutor(线程池)
- ThreadPoolExcutor(线程池)初识
- ThreadPoolExcutor(线程池)初识
- 源码分析
- 源码分析
- 源码分析
- 源码分析
- 源码分析
- 源码分析
- 源码分析
- 源码分析
- Android中对ThreadPoolExcutor的简单使用
- 源码分析:SparseArray分析
- 进程间的几种通信方式概述
- springmvc 基础
- Linux/Ubuntu下解压命令
- 如何测试sql语句性能,提高执行效率
- Unicode格式字符串之间转换
- ThreadPoolExcutor源码分析
- 搭建一个简单的mvc(一)
- 局部代码块
- 栈增长方向与大端/小端问题
- 如何测试sql语句性能,提高执行效率
- 极客学院----H5的相关笔记----css基础(一)
- RxJava是什么?
- [C++编程] -- 虚函数与多态
- TEC1701.WebADI开发技术总结 - 第六章 Web ADI开发常见问题(6/6)