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的基础上提供了对任务执行的生命周期的管理,主要是submitshutdown方法。

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;}



AbstractExecutorServiceExecutorService一些方法做了默认的实现,主要是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状态:不再接受新任务,不处理队列中的任务

状态转换:
1. Running ->shutdown: shutdown(),可能暗含在finalize中
2. Running /shutdown -> stop: shotdownNow
3. shutdown -> tidying: 当队列和线程池都为空
4. stop -> TIDYING: 当线程池为空
5. tidying->terminated: terminated()完成
当状态变为teminated时,线程在awaitTermination()中的等待会返回。

围绕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框架实现了一个简单的非重入的互斥锁, 实现互斥锁主要目的是为了中断的时候判断线程是在空闲还是运行,可以看后面shutdownshutdownNow方法的分析(
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状态下没有活动线程了,但是队列里还有任务没执行这种特殊情况。

6.addWorker
/*     * 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;// 线程被中断重试            }        }    }


9.ProcessWorkerExit

线程退出会执行这个方法做一些清理工作。

/**     * 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的主要作用。












0 0
原创粉丝点击