• 线程池执行器ThreadPoolExecutor源码完整解读


    1 前言

    ThreadPoolExecutor的基本概念和用法已经在之前的文章线程池ThreadPoolExecutor简介Executor框架完整解读中做过详细的说明,这里主要基于JDK1.8对ThreadPoolExecutor从源码级别分析其实现原理。

    ThreadPoolExecutorExecutorService的最重要的实现类,ThreadPoolExecutor不直接实现ExecutorService接口,它直接继承于AbstractExecutorService抽象类(AbstractExecutorService的源码实现在AbstractExecutorService源码完全解析已做过分析。)AbstractExecutorServiceExecutorSerivice接口中的一些方法做过的默认实现 。

    线程池有两个重要的概念一个是任务队列,另一个是工作者线程 。
    任务队列是存放任务的容器,工作者线程会依次不断地到队列中获取任务并执行。

    2 重要的成员内部类Worker

    Worker继承于AbstractQueuedSynchronizer抽象类,它又实现了Runnable接口。
    Worker可以理解为一个工作者线程,但内部属性又不只有一个Thread属性,除此之外还有首任务firstTask、线程所完成的任务数completedTasks。
    Worker类主要是维护执行任务的线程的中断状态的控制,及其他次要的一些标记功能。它继承AQS,它相当于一个不可重入的排他锁.

    1) 成员变量

    thread表示Worker执行任务的线程,firstTask表示worker执行的第一个任务(对于后来的其他任务它会到任务队列中去获取),completedTasks表示当前worker线程所完成的任务数

    /** Thread this worker is running in.  Null if factory fails. */
    final Thread thread;// 一般不为空,这由ThreadFactory决定  
    /** Initial task to run.  Possibly null. */
    Runnable firstTask;//可能为空
    /** Per-thread task counter */
    volatile long completedTasks;//此工作线程完成的任务数

    2) 构造方法

    构造方法主要涉及对成员变量的初始化,方法体内调用了父类AQS的setState方法将state置为负数-1,它的主要目的是防止线程被过早中断,直到runWorker开始执行任务时才清除state的负数状态(成员内部类的一个对象与外部类的对象相互绑定,成员内部类可直接访问外部类的全局变量和实例、静态方法)

    Worker(Runnable firstTask) {
        setState(-1); // inhibit interrupts until runWorker 调用AQS的setState,设置状态
        this.firstTask = firstTask; 
        //getThreadFactory是外部类的ThreadPoolExecutor的实例方法,返回一个实现ThreadFactory接口的对象.
        //newThread根据当前worker所代表(Worker实现了Runnable接口,worker也是Runnable对象)的Runnable对象
        //创建一个线程对象。所以this.thread线程启动就会执行worker.run().
        this.thread = getThreadFactory().newThread(this);
    }

    3) 方法实现

    ①run方法

    run方法是执行任务方法,它直接委托给外部类ThreadPoolExecutor的runWorker方法来实现,runWorker方法的实现细节在之后会详细说明。

    /** Delegates main run loop to outer runWorker  */
    public void run() { //
        ////当Worker.thread.start()调用后,Worker.thread线程启动,就会执行这里的run方法,run方法又委托给runWorker
        //换句话说,worker线程启动后,最终会执行runWorker方法。
        runWorker(this);
    }

    ②与锁相关的方法

    isHeldExclusivelytryAcquiretryRelease这3个方法均是父类AQS的模板方法所调用的应被重写的方法,其具体原理在之前AbstractQueuedSynchronizer实现原理分析帖子中做过说明,这里不再细说。

    locktryLockunlockisLocked这4个方法也与显式锁ReentrantLock实现原理基本一致,之前对ReentrantLock的实现做过说明,这里也不再细说。

    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) {
        //与ReentrantLock的区别在于,这里未检测在释放锁前是否已获得锁
        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(); }

    ③interruptIfStarted中断线程,调用此方法可以在任务启动后中断线程。

    void interruptIfStarted() {
        Thread t;
        //state不能小于0,为负数表明worker线程还未启动
    //(在构造方法中将state初始为-1,在worker线程启动后runWorker方法开头处的w.unLock会将state置为0)
        //!t.isInterrupted()如果线程已经是中断状态,也不需要再去中断它了。
        if (getState() >= 0 && (t = thread) != null && !t.isInterrupted()) {
            try {
                t.interrupt();
            } catch (SecurityException ignore) {
            }
        }
    }

    3 内置的拒绝策略

    ThreadPoolExecutor内部实现了4种拒绝策略,默认使用AbortPolicy策略,这4种拒绝策略都实现RejectedExecutionHandler接口,这4个类都是ThreadPoolExecutor的静态内部类。当线程池执行器饱和时,会调用RejectedExecutionHandler的rejectedExecution方法处理任务。

    • CallerRunsPolicy, 使用任务提交者的所在线程执行任务;
    • AbortPolicy,直接抛出异常,这是默认的拒绝策略;
    • DiscardPolicy, 不执行任务,将任务丢弃;
    • DiscardOldestPolicy,丢弃队列中最近的任务,然后执行当前任务
    public static class CallerRunsPolicy implements RejectedExecutionHandler {
      public CallerRunsPolicy() { }
      //使用调用者的线程执行任务
      public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
        if (!e.isShutdown()) {
          r.run();
        }
      }
    }
    
    public static class AbortPolicy implements RejectedExecutionHandler {
      public AbortPolicy() { }
      //直接抛出异常
      public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
        throw new RejectedExecutionException("Task " + r.toString() +
                " rejected from " +
                e.toString());
      }
    }
    
    public static class DiscardPolicy implements RejectedExecutionHandler {
      public DiscardPolicy() { }
      //啥也不做,丢弃任务
      public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
      }
    }
    
    public static class DiscardOldestPolicy implements RejectedExecutionHandler {
      public DiscardOldestPolicy() { }
      //丢弃队列中最近的任务,然后执行当前任务
      public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
        if (!e.isShutdown()) {
          e.getQueue().poll();
          e.execute(r);
        }
      }
    }
    View Code

    4 静态常量与成员变量

    ThreadPoolExecutor有一个重要的成员变量ctl,它是一个int型的原子变量,它是线程池执行器状态控制的主要属性。它复合了线程池执行器的两个重要状态,一个是workerCount,它表示有效线程数,另一个是runState,它表示线程池执行器是否正在运行、正在关闭等。ctl共有32个二进制位,runState占用ctl的高3位,workerCount占用ctl的低29位,可调用runStateOf(ctl)方法来取ctl的高3位,可调用workerCountOf(ctl)方法来取ctl的低29位,另外还可调用ctlOf(runState, workerCount)根据runState、workerCount算出ctl的值。

    //线程池主要的状态控制属性
    //初始值为-536870912,二进制开形式为 0b10100000_00000000_00000000_00000000
    private final AtomicInteger ctl = new AtomicInteger(ctlOf(RUNNING, 0));
    //workerCount在ctl中的二进制位数,占29位
     private static final int COUNT_BITS = Integer.SIZE - 3;  //29
    //workerCount的最大值, 二进制形式    0b00011111_11111111_11111111_11111111;
    private static final int CAPACITY   = (1 << COUNT_BITS) - 1;//536870911
    
    // runState is stored in the high-order bits
    //表示ctl中的最高3位的runState值
    private static final int RUNNING    = -1 << COUNT_BITS;//二进制形式 0b10100000_00000000_00000000_00000000
    private static final int SHUTDOWN   =  0 << COUNT_BITS;//二进制形式 0b00000000_00000000_00000000_00000000
    private static final int STOP       =  1 << COUNT_BITS;//二进制形式 0b00100000_00000000_00000000_00000000
    private static final int TIDYING    =  2 << COUNT_BITS;//二进制形式 0b01000000_00000000_00000000_00000000
    private static final int TERMINATED =  3 << COUNT_BITS;//二进制形式 0b01100000_00000000_00000000_00000000
    
    // Packing and unpacking ctl
    private static int runStateOf(int c)     { 
        return c & ~CAPACITY; //c & 0b11100000_00000000_00000000_00000000
    }
    private static int workerCountOf(int c)  {
        return c & CAPACITY;  //c & 0b00011111_11111111_11111111_11111111
    } 
    private static int ctlOf(int rs, int wc) { return rs | wc; }

    workerCount是已被允许启动但不允许停止的工作线程数。 该值可能与活动线程的实际数量暂时不等,例如,当ThreadFactory在被要求创建,但创建线程失败,该值会与之不等。 用户可见的线程池大小为workers.size()(workers是一个HashSet类型的对象,它是也是一个成员变量,用来存放Worker的容器)

    runState提供线程池执行器主要的生命周期控制,它有以下几种可取的值:

    • RUNNING:接受新任务并处理排队的任务
    • SHUTDOWN:不接受新任务,但处理已入队的任务
    • STOP:不接受新任务 、不处理已入队的任务,并中断执行中的任务
    • TIDYING:过渡状态,即将转为TERMINATED。 此时所有任务已终止,workerCount为零,将线程的状态设为TIDYING,并将调用回调方法Terminated()
    • TERMINATED:方法terminate()已执行完

    runState是有序的,它随时间单调增加,但其生命周期并非一定会经历下面的所有状态。状态转换过程是

    • RUNNING -> SHUTDOWN:在调用shutdown()时,可能隐式在finalize()中调用
    • RUNNING/SHUTDOWN -> STOP:调用shutdownNow()
    • SHUTDOWN -> TIDYING:当任务队列和工作者线程池都为空时
    • STOP -> TIDYING:当工作者线程池为空时
    • TIDYING -> TERMINATED:当terminate()已执行完时

    状态变为TERMINATED时,在awaitTermination()中等待的线程将返回。
    检测到从SHUTDOWN到TIDYING间的状态转换并不简单,因为在SHUTDOWN状态期间,任务队列在非空之后可能会变空,反之亦然,但是只有在看到它为空之后才能看到workerCount 为0 。

    其它字段

    private final ReentrantLock mainLock = new ReentrantLock();
    private final HashSet<Worker> workers = new HashSet<Worker>();
    private final Condition termination = mainLock.newCondition();
    private int largestPoolSize;
    private long completedTaskCount;
    //构造方法的要参数对应初始化的成员变量
    private final BlockingQueue<Runnable> workQueue;
    private volatile ThreadFactory threadFactory;
    private volatile RejectedExecutionHandler handler;
    private volatile long keepAliveTime;
    private volatile int corePoolSize;
    private volatile int maximumPoolSize;
    
    private volatile boolean allowCoreThreadTimeOut;
    private static final RejectedExecutionHandler defaultHandler =
            new AbortPolicy();
    private static final RuntimePermission shutdownPerm =
            new RuntimePermission("modifyThread");
    private final AccessControlContext acc;
    private static final boolean ONLY_ONE = true;

    mainLock: 一个可重入的排他锁,这个锁主要是保证访问属性workers的线程安全及与之相关清除、标记 。
    workers:它保存所有的工作者线程,访问此属性前必须先获得mainLock锁。
    termination:一个等待条件,此属性主要为awaitTermination()方法中的线程通信提供支持。
    largestPoolSize:反映线程池实际曾达到的最大线程数 ,访问此属性前必须先获得mainLock锁。
    completedTaskCount:线程池已完成的任务数,它只会在工作者线程终止时更新,访问此属性前必须先获得mainLock锁。
    workQueue、 threadFactory、 handler、 keepAliveTime 、corePoolSize 、maximumPoolSize这6个属性,在之前的文章中有过说明,这里不再赘述。
    allowCoreThreadTimeOut: 此属性默认为false. 如果它为false,则即使处于空闲状态,核心线程也保持活动状态; 如果为true,则核心线程使用keepAliveTime超时等待任务。
    defaultHandler:默认的拒绝策略,当线程池饱和后,只要有新任务到达它就会直接抛出异常。
    shutdownPerm 、acc:均是安全权限相关的字段。
    ONLY_ONE: 中断时默认只中断一个工作者线程,tryTerminate方法会用到此常量

    5 构造方法

    ThreadPoolExecutor有4个构造方法,分别需要若干个参数,构造方法只简单地涉及对成员变量的初始化,其参数个数最多的构造方法共有7个参数,其他的构造方法都是直接调用这个构造方法来实现的(各个参数的含义在线程池ThreadPoolExecutor简介 有详细说明)

    public ThreadPoolExecutor(int corePoolSize,
                              int maximumPoolSize,
                              long keepAliveTime,
                              TimeUnit unit,
                              BlockingQueue<Runnable> workQueue,
                              ThreadFactory threadFactory,
                              RejectedExecutionHandler handler) {
      if (corePoolSize < 0 ||
              maximumPoolSize <= 0 ||
              maximumPoolSize < corePoolSize ||
              keepAliveTime < 0)
        throw new IllegalArgumentException();
      if (workQueue == null || threadFactory == null || handler == null)
        throw new NullPointerException();
      this.acc = System.getSecurityManager() == null ?
              null :
              AccessController.getContext();
      this.corePoolSize = corePoolSize;
      this.maximumPoolSize = maximumPoolSize;
      this.workQueue = workQueue;
      this.keepAliveTime = unit.toNanos(keepAliveTime);
      this.threadFactory = threadFactory;
      this.handler = handler;
    }
    View Code

    6 主要方法

    execute是线程池执行器的入口方法,它会调用addWorker创建并启动(thread.start)工作者线程,而工作者线程启动后又会调用runWorker去执行任务。因此可以看出execute、 addWorker 、runWorker 是线程池执行器最重要的3个方法(点击绿色的方法名快速跳至目标方法)

    1) 成员变量ctl相关方法

    runStateOf(ctl)方法来取ctl的高3位,获取runState,
    workerCountOf(ctl)方法来取ctl的低29位,获取workerCount
    ctlOf(runState, workerCount)根据runState、workerCount算出ctl的值。
    runStateLessThan(int,int)返回第一个参数(表示runState)是否小于第二个参数的布尔值
    runStateAtLeast返回第一个参数(表示runState)是否大于等于第二个参数的布尔值
    isRunning(int)返回runState是否为RUNNING(接受新任务并处理排队的任务)的布尔值
    compareAndIncrementWorkerCount(int)尝试CAS更新ctl,将workerCount加1
    compareAndDecrementWorkerCount(int)尝试CAS更新ctl,将workerCount减1
    decrementWorkerCount(int)CAS自旋更新ctl,只有成功将workerCount减1,方法才能返回
    advanceRunState(int targetState) 将runState设为targetState,若runState已经至少targetState级别则不改变原runState值。

    private static int runStateOf(int c)     { return c & ~CAPACITY; }
    private static int workerCountOf(int c)  { return c & CAPACITY; }
    private static int ctlOf(int rs, int wc) { return rs | wc; }
    private static boolean runStateLessThan(int c, int s) {
        return c < s;
    }
    private static boolean runStateAtLeast(int c, int s) {
        return c >= s;
    }
    private static boolean isRunning(int c) {
        return c < SHUTDOWN;
    }
    private boolean compareAndIncrementWorkerCount(int expect) {
        return ctl.compareAndSet(expect, expect + 1);
    }
    private boolean compareAndDecrementWorkerCount(int expect) {
        return ctl.compareAndSet(expect, expect - 1);
    }
    private void decrementWorkerCount() {
        do {} while (! compareAndDecrementWorkerCount(ctl.get()));
    }
    private void advanceRunState(int targetState) {
       for (;;) {
            int c = ctl.get();
            if (runStateAtLeast(c, targetState) ||
                ctl.compareAndSet(c, ctlOf(targetState, workerCountOf(c))))
                break;
        }
    }
    View Code

    2) interruptWorkers系列方法

    1) interruptIdleWorkers(boolean)

    interruptIdleWorkers的实现比较简单,它在执行核心逻辑之前要先获取两类锁,一个锁是mainLock锁,另一个锁是Worker本身的锁。它遍历所有Worker中对应的线程,若线程是未被中断且是空闲线程就中断此线程 。若参数onlyOne是true,则最多只会中断一个空闲线程。

        private void interruptIdleWorkers(boolean onlyOne) {
            final ReentrantLock mainLock = this.mainLock;
            mainLock.lock();//获取mainLock
            try {
                for (Worker w : workers) {
                    Thread t = w.thread;
                    //线程已经是中断状态就不再中断它
                    //尝试获取worker锁,允许抢锁失败。
                    //若抢锁失败表明worker线程正在执行任务,它不是空闲线程,准备去获取下一个worker锁
                    if (!t.isInterrupted() && w.tryLock()) {
                        try {
                            t.interrupt();
                        } catch (SecurityException ignore) {
                        } finally {
                            w.unlock();
                        }
                    }
                    if (onlyOne)//onlyOne是true,就只中断一个空闲线程,然后退出
                        break;
                }
            } finally {
                mainLock.unlock();
            }
        }
    View Code

    2) interruptIdleWorkers()

    interruptWorkers()中断线程池中所有的空闲线程 ,我们来看看interruptWorkers()如何实现的。

    interruptIdleWorkers()直接委托给interruptIdleWorkers(boolean)去实现,上面已经对interruptIdleWorkers(boolean)分析过了,这里就不再说了。

       private void interruptIdleWorkers() {
            interruptIdleWorkers(false);
        }

    3) interruptWorkers()

    interruptWorkers()中断所有已启动线程, 我们来看看interruptWorkers()如何实现的。
    interruptWorkers方法很简单,它先获取mainLock锁,然后遍历所有worker线程,并中断已启动的worker线程。

    private void interruptWorkers() {
        final ReentrantLock mainLock = this.mainLock;
        mainLock.lock();
        try {
            for (Worker w : workers)
                w.interruptIfStarted();//中断已启动的worker线程(active thread,即线程的start方法已被调用)
        } finally {
            mainLock.unlock();
        }
    }

    3) terminate系列方法

    (1) isTerminating()

    isTerminating()返回线程池执行器是否正在被终止的布尔值,此方法不是ExecutorService接口中的方法,这是ThreadPoolExecutor自身添加的一个API。这种状态一般出现在①shutdown 、②shutdownNow、③ tryTerminate方法调用后(tryTerminate中CAS成功将runState更新为TIDYING但调用terminate()方法还未执行完的时候)

       public boolean isTerminating() {
            int c = ctl.get();
            //runState>=SHUTDOWN 且runState<TERMINATED ,那么runState则可能是SHUTDOWN、STOP、TIDYING其中之一
            return ! isRunning(c) && runStateLessThan(c, TERMINATED);
        }

    (2) isTerminated()

    isTerminating()返回线程池执行器是否已被终止的布尔值。

       public boolean isTerminated() {
            //runState>=TERMINATED ,此时runState只能是TERMINATED
            return runStateAtLeast(ctl.get(), TERMINATED);
        }

    (3) awaitTermination()

    awaitTermination()阻塞等待所有任务完成。此方法需要设置超时时间,它会阻塞当前线程直到所有任务完成(返回ture)或发生超时(返回false)或当前线程被中断。

    public boolean awaitTermination(long timeout, TimeUnit unit)
            throws InterruptedException {
        long nanos = unit.toNanos(timeout);
        final ReentrantLock mainLock = this.mainLock;
        mainLock.lock();//获取锁
        try {
            for (;;) {
                //runState是否为TERMINATED 。TERMINATED状态时,所有任务已终止,线程池为空。
                if (runStateAtLeast(ctl.get(), TERMINATED))
                    //已经是TERMINATED了,返回true
                    return true;
                if (nanos <= 0)//已经超时,返回false
                    return false;
                //当前线程阻塞等待,
    //直到“达到超时时间”或“被termination.signal通知"(tryTerminate会调用termination.signalAll) 时
                //当前线程才能被唤醒
                nanos = termination.awaitNanos(nanos);
            }
        } finally {
            mainLock.unlock();
        }
    }
    awaitTermination

    (4) tryTerminate()

    tryTerminate()检查runState否应转为TERMINATED状态,若状态应该转换则执行相应的teminate工作.

    其实现细节是:
    ①若是在“runState是RUNNING状态”或“runState至少是TIDYING状态”或“runState是SHUTDOWN但队列中还有任务”这三种情况下,将runState不能转为TERMINATED ,方法直接返回。反之则进入下一步。
    ②再检查线程数workerCount是否为零,若workerCount不为零则调用interruptIdleWorkers中断一个空闲线程 ,反之则进入下一步。
    ③先获取mainLock锁 ,然后CAS尝试将runState设为TIDYING(这里cas更新失败将自旋重试),再然后执行terminated()(空方法,留给子类实现)方法,待terminated()执行完后,再将runState无条件设为TERMINATED并唤醒等待termination条件的所有线程

        final void tryTerminate() {
            for (; ; ) {
                int c = ctl.get();
                if (isRunning(c) ||//runState是RUNNING状态
                        runStateAtLeast(c, TIDYING) || //至少是TIDYING状态
                        (runStateOf(c) == SHUTDOWN && !workQueue.isEmpty()))//runState是SHUTDOWN但队列中还有任务
                    //这三种情况下不能将runState转为TERMINATED,方法直接返回
                    return;
                //runState可以转为TERMINATED,但池中还有一些线程,就中断池中一个空闲线程,然后方法返回
                if (workerCountOf(c) != 0) { // Eligible to terminate
                    interruptIdleWorkers(ONLY_ONE);//中断一个空闲线程
                    return;
                }
                //runState可以转为TERMINATED且池中没有任何线程时
                //
                final ReentrantLock mainLock = this.mainLock;
                mainLock.lock();
                try {
                    //尝试CAS更新,将runState设为TIDYING
                    // (TIDYING状态表示所有任务都已终止且线程数workerCount为零)
                    if (ctl.compareAndSet(c, ctlOf(TIDYING, 0))) {
                        try {
                            terminated();//空方法,留后子类实现
                        } finally {
                            //terminated执行后,无条件地将runState设为TERMINATED状态
                            //(TERMINATED状态表示terminated方法执行完成)
                            ctl.set(ctlOf(TERMINATED, 0));
                            //唤醒等待termination条件的所有线程
                            termination.signalAll();
                        }
                        return;
                    }
                } finally {
                    mainLock.unlock();
                }
                // else retry on failed CAS
            }
        }
    tryTerminate

    4 )addWorker系列方法

    (1) addWorker(Runnable,boolean)

    addWorker是一个重要的方法,它的主要作用是启动工作者线程Worker,其返回值表示启动Worker是否成功。它有两个参数,第一个参数是新创建线程的第一个执行的任务(可以为空),第二个参数是表示是否为核心线程的布尔值.

     它的主要逻辑分为两部分

    ①第一部分是两层for循环自旋,它主要是检查runState、workerCount,并将workerCount加1 。
    细节上是:先检查执行器是被关闭且工作队列为空,若是,则直接返回false。然后再检查线程数是否超出给定的边界值(核心线程数或可允许最大线程数值),若超出则直接返回false。尝试CAS更新workerCount,将workerCount加1,若CAS更新成功,则退出for循环,进入下一部分,若CAS更新失败,则需再次进入内循环自旋重试。若runState被其他线程修改了,则要重新进入外层循环重试。
    ②第二部分主体是一个try-finally块,它主要先获取mainLock锁,再向成员变量workers中添加一个worker对象,若添加失败则调用addWorkerFailed进行回滚。
    细节上是:先尝试创建并启动一个新的worker(worker.thread.start()启动后,runworker方法会执行)。如果线程工厂无法创建线程(创建的线程为null),将返回false。 如果线程池已停止或即将关闭,也将返回false。 如果worker线程启动失败(由于线程工厂返回null或发生异常),将调用addWorkerFailed进行回滚。

      private boolean addWorker(Runnable firstTask, boolean core) {
        /**
         * 主要是检查runState 和workerCount,时机合适就将workerCount加1
         */
        retry:
        for (;;) {
          int c = ctl.get();
          int rs = runStateOf(c);//获取runState
    
          // Check if queue empty only if necessary.
          //如果线程池已关闭且工作队列为空,添加Worker失败,直接返回false
          if (rs >= SHUTDOWN &&
                  ! (rs == SHUTDOWN &&
                          firstTask == null &&
                          ! workQueue.isEmpty()))
            return false;
    
          for (;;) {
            int wc = workerCountOf(c);//获取线程数workerCount
            if (wc >= CAPACITY ||
                    wc >= (core ? corePoolSize : maximumPoolSize))//不能大于corePoolSize 、maximumPoolSize
              //线程数大于规定的线程数(最大容量的线程数,配置的核心线程数、配置的可允许最大线程数)
              // ,添加Worker失败,返回false
              return false;
            if (compareAndIncrementWorkerCount(c))//CAS失败,需要再次进入内循环自旋重试
              //workerCount加1成功,退出外层for循环 ,线程数已更新,
              // 接下来进入实际添加的向成员变量workers中Worker操作
              break retry;
            c = ctl.get();  // Re-read ctl
            if (runStateOf(c) != rs)//runState被其他线程修改了,需要跳到外层for循环的开头处重试
              continue retry;
            // else CAS failed due to workerCount change; retry inner loop
          }
        }
          
        /**
         * 向成员变量workers中添加worker,
         * 若无法添加worker或线程启动失败,则要调用addWorkerFailed进行回滚
         */
        boolean workerStarted = false;//worker线程是否启动的标志
        boolean workerAdded = false;//worker是否添加成功的标记
        Worker w = null;
        try {
          w = new Worker(firstTask);
          final Thread t = w.thread;
          //t是线程工厂创建出来的线程,可以自己重写ThreadFactory接口的newThread方法,
          // newThread返回值是否为空不确定,这里有必要对t进行非空判断
          if (t != null) {
            final ReentrantLock mainLock = this.mainLock;
            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状态或虽处于SHUTDOWN状态但任务为空 ,总之线程池还是可用的
              if (rs < SHUTDOWN ||
                      (rs == SHUTDOWN && firstTask == null)) {
                //预先检查线程是否已经被启动了
                if (t.isAlive()) // precheck that t is startable
                    //线程已预先被启动了,抛出异常
                  throw new IllegalThreadStateException();
                workers.add(w);//添加worker对象到workers集合中
                int s = workers.size();
                //检查更新largestPoolSize(表示线程池实际曾达到的最大线程数)
                if (s > largestPoolSize)
                  largestPoolSize = s;
                workerAdded = true;//更新worker是否添加成功的标记
              }
            } finally {
              mainLock.unlock();//释放锁
            }
            if (workerAdded) {//worker成功添加后,启动线程
              t.start();//worker.run方法将执行,worker.run又会调用runWorker()
              workerStarted = true;//更新worker线程是否启动的标志
            }
          }
        } finally {
          if (! workerStarted)
       //添加worker失败,(根据前面的逻辑可看出,在未发生异常时,workerAdded若是false,workerStarted则也为false)
      //就调用addWorkerFailed(),对addWorker方法进行回滚
            addWorkerFailed(w);
        }
        return workerStarted;
      }
    addWorker

    (2) addWorkerFailed(Worker)

    addWorkerFailed主要是回滚创建worker线程的失败。
    它先要获取mainLock锁,然后它做了3件事:
    ①从workers中移除这个worker;
    ②将workerCount减1;
    ③检查runState否应转为TERMINATED状态,若是则执行相应的teminate工作。

        private void addWorkerFailed(Worker w) {
            final ReentrantLock mainLock = this.mainLock;
            mainLock.lock();//先获取锁
            try {
                if (w != null)
                    workers.remove(w);//从workers中移除worker
                decrementWorkerCount();//将workerCount减1
                tryTerminate();//尝试终止线程池
            } finally {
                mainLock.unlock();
            }
        }

    5) runWorker相关方法

    (1) runWorker(Worker)

     runWorker(Worker)主要从任务队列中获取任务执行。核心逻辑:

    ①将Worker的state从-1置为0(调用worker.unlock),保证之后worker线程能被中断、worker锁能被获取。
    ②到worker.firstTask属性或任务队列中获取任务。若获取的任务不为空就进入下一步,反之则worker线程准备终止,进入步骤6。
    ③获取woker锁,准备执行任务。
    ④检查runState,若runState是STOP级就确保当前线程是中断的,若runState不是STOP级就确保当前线程之后不是中断的。
    ⑤调用task.run开始执行任务,捕获执行任务过程中可能出现的异常。在任务执行完后,将worker的任务完成数completedTasks加1,再释放worker锁。再次获取任务,跳回步骤2。
    ⑥在worker线程即将终止退出(包括因异常退出的情况)时,执行processWorkerExit方法处理worker终止的后续工作

    final void runWorker(Worker w) {
        Thread wt = Thread.currentThread();
        Runnable task = w.firstTask;//
        //在获取w.firstTask后,将w.firstTask设为空,因为之后worker会到任务队列中获取任务
        w.firstTask = null;
    //这里并不是真的释放锁,而只是将父类AQS的state从初始的-1置为0。
    //否则worker线程不能被中断(worker初始化时state为-1,interruptIfStarted方法中要求state>0才中断线程),
    //worker锁也一直无法被获取(尝试获取锁时compareAndSetState(0, 1)返回true才能成功抢锁,若state为-1,它永远返回false)
        w.unlock(); // allow interrupts 
        boolean completedAbruptly = true; //worker异常终止的标志
        try {
            //firstTask不空或任务队列中还能获取到任务,
            while (task != null || (task = getTask()) != null) {
                //成功获取到worker锁后,表明worker线程就要执行任务,不再是空闲状态了。
                //w.isLock可以判断线程是否空闲等待,如果返回false,表明worker线程在空闲等待
                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
    
      //如果runState是STOP且线程未被中断,就使用wt.interrupt()中断线程,确保wt是中断的;
     //如果runState不是STOP就用Thread.interrupted()保证之后wt不是中断状态
     //(若某线程t是中断状态,调用静态方法Thread.interrupted()会在清除线程t的中断标记后 
     //返回true,下次调用实例方法t.isInterrupted()将返回false,这是因为中断标记之前已被清除)
                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++;//已完成任务数加1
                    w.unlock();
                }
            }
            completedAbruptly = false;//worker没有因异常死亡
        } finally {
            processWorkerExit(w, completedAbruptly);//清除和标记woker终止后的后续工作
        }
    }
    runWorker

    (2) getTask()

    getTask()从任务队列获取任务。其核心逻辑:
    ①检查runState,若runState状态表明执行器不需要再执行任务(“runState>=STOP” 或 “runState>=SHUTDOWN且任务队列为空”)时,将workerCount减1,返回空任务,此worker线程即将终止。反之则进入下一步
    ②若当前线程数大于maximumPoolSize或等待任务出队超时或任务队列为空时,就尝试CAS将workerCount减1,反之则进入步骤3。 若CAS更新workerCount成功则返回空任务,反之则自旋重试,跳回步骤1。
    ③阻塞等待任务出队,如果任务出队成功,就返回这个任务,反之则自旋重试,跳回步骤1。

    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.
            //“runState>=STOP” 或  “runState>=SHUTDOWN且任务队列为空”,
            // 表明执行器已经关闭了,worker线程将终止,返回空任务,worker不再执行任务。
            if (rs >= SHUTDOWN && (rs >= STOP || workQueue.isEmpty())) {
                decrementWorkerCount();//因工作线程退出,workerCount减1
                return null;
            }
    
            int wc = workerCountOf(c);
    
            // Are workers subject to culling?
            //是否要应用超时策略的布尔值(中断空闲线程)
            boolean timed = allowCoreThreadTimeOut || wc > corePoolSize;
                //wc > maximumPoolSize  workerCount大于maximumPoolSize,因为maximumPoolSize被重设了
                // timed && timedOut    在运用超时策略时最终还真的等待超时了
                // "wc >1 || workQueue.isEmpty()"当前只有一个线程或任务队列空了
            if ((wc > maximumPoolSize || (timed && timedOut))
                    && (wc > 1 || workQueue.isEmpty())) {
                //尝试CAS将workState减1
                if (compareAndDecrementWorkerCount(c))
                    //CAS更新成功,返回空任务
                    return null;
                continue;//CAS更新失败,自旋重试获取任务
            }
    
            try {
                //如果要应用超时策略,就等待指定时长让任务出队,
                //若不应用超时策略,就无限长时间地等待任务出队
                Runnable r = timed ?
                        workQueue.poll(keepAliveTime, TimeUnit.NANOSECONDS) :
                        workQueue.take();
                if (r != null)
                    return r;//成功出队了,返回此任务
                timedOut = true;//poll返回null,等待超时了
            } catch (InterruptedException retry) {
                timedOut = false;
            }
        }
    }
    getTask

    (3) processWorkerExit(Worker,boolean)

    processWorkerExit(Worker,boolean)处理worker线程终止退出的后续扫尾工作。
    其主要逻辑:
    ①若worker线程是因异常而突然终止的,就将workerCount减1
    ②获取manLock锁,将worker.completedTasks同步到ThreadPoolExecutor.completedTaskCount中,从workers中移除这个即将终止的worker
    ③检查runState是否应转为TERMINATED状态及与之相关的处理
    ④当runState<=STOP时,如果时机合适就启动一个新worker来替代即将终止的worker

    private void processWorkerExit(Worker w, boolean completedAbruptly) {
    
        if (completedAbruptly) // If abrupt, then workerCount wasn't adjusted
          //worker因异常而终止,workerCount不能自适应改变,手动将workerCount减1
            decrementWorkerCount();//
    
        final ReentrantLock mainLock = this.mainLock;
        mainLock.lock();
        try {
            //当一个worker终止时,需要将其completedTasks同步到ThreadPoolExecutor.completedTaskCount上
            completedTaskCount += w.completedTasks;
            workers.remove(w);//从成员变量workers中移除这个worker
        } finally {
            mainLock.unlock();
        }
    
        tryTerminate();//检查runState是否应转为TERMINATED状态及与之相关的处理
    
        int c = ctl.get();
        //runState是RUNNING或SHUTDOWN时,这两种情况下还可以启动worker
        if (runStateLessThan(c, STOP)) {
            if (!completedAbruptly) {//worker正常死亡时 判断是需要启动新worker来替代已死的worker
                //min表示线程池中能长久驻存的线程数(不会因长久空闲等待而终止的线程数)
                int min = allowCoreThreadTimeOut ? 0 : corePoolSize;
                if (min == 0 && ! workQueue.isEmpty())
                    //只有一个长久驻存的线程但队列中还有任务
                    min = 1;
                if (workerCountOf(c) >= min)
                    //当前线程数多于能长久驻存的线程数,不需要启动新worker来替代已死的worker,直接返回
                    return; // replacement not needed
            }
            //启动新的worker替代已死worker
            addWorker(null, false);
        }
    }
    processWorkerExit

    6) execute(Runnable)

    execute(Runnable)方法非常重要,它是ThreadPoolExecutor的入口方法,父类AbstractExecutorService已实现ExecutorService接口中的sumbit 、invokeXXX方法,这些方法的核心逻辑都委托给execute实现,详细说明见之前的文章AbstractExecutorService源码完全解析

     execute(Runnable)的核心逻辑分为三步:

    ①如果当前有效线程数少于corePoolSize,则调用addWorker尝试启动一个核心线程执行任务。若成功启动,方法就直接返回,反之则进入下一步。
    ②若执行器还在运行(runState=RUNNING)且任务入队成功,则需要再次检查workerCount和runState, 反之则进入步骤3。若执行器已关闭(runState>RUNNING)且成功将刚入队的任务从队列中移除,则使用拒绝策略处理此任务;反之再检查当前有效线程数是否为零,若实际线程数为零,则新启动一个非核心线程(保证线程池中至少有一个线程)。
    ③(一般是队列已满)尝试启动一个非核心线程去执行此任务。 如果启动失败则表明执行器已关闭或已饱和,因此使用拒绝策略处理此任务。

        public void execute(Runnable command) {
          if (command == null)
            throw new NullPointerException();
          int c = ctl.get(); //先获取原子变量ctl的值
          //工作者线程数少于corePoolSize,
          if (workerCountOf(c) < corePoolSize) {
            if (addWorker(command, true))//尝试创建核心线程执行任务
              return;//成功就返回
            c = ctl.get();//若失败(可能是执行器被关闭了或线程启动失败),要重新获取ctl值
          }
          //工作者线程数大于等于corePoolSize,意味着要尝试将任务放入队列到队列中
          //isRunning(c)线程池能接受任务
          //workQueue.offer(command)任务入队成功
          if (isRunning(c) && workQueue.offer(command)) {
            //重新获取ctl,将再次检查runState和workerCount因为有可能上次检查后线程被终止了或线程池被关闭了
            int recheck = ctl.get();
            //线程池已关闭时尝试将这个已入队的任务从队列中移除(上面的"workQueue.offer(command)"已成功入队)
            if (! isRunning(recheck) && remove(command))
              //移除任务成功时,使用拒绝策略处理任务
              reject(command);//
            //"线程池已关闭且从任务队列中移除任务失败(可能是任务已被完成了)" 或"线程池还处于RUNNING状态"
            //将检查池中的线程数是否为0
            else if (workerCountOf(recheck) == 0)
              //线程数为零时, 创建非核心线程,但不立即执行任务(这里的addWorker中的Runnable为空) 
              // 因为之前已经将此任务放入工作队列了,空闲线程会到队列中去获取任务来执行
              addWorker(null, false);
          }
          //入队失败,可能是因为队列已满,尝试创建一个非核心线程去执行任务
          else if (!addWorker(command, false))
            //addWorker失败,使用拒绝策略处理任务
            reject(command);
        }
    execute

     上面的execute中调用了几个我们不熟悉的方法,分别是remove(Runnable)reject(Runnable),下面我们分别来看看这两个方法。

    (1) remove(Runnable)

    remove(Runnable)方法逻辑很简单,就是先将任务从任务队列中移除,再调用tryTerminate()检查是否应转为TERMINATED状态及其相关的处理,最后返回是否成功移除任务的布尔值。

        public boolean remove(Runnable task) {
            boolean removed = workQueue.remove(task);
            tryTerminate(); // In case SHUTDOWN and now empty
            return removed;
        }

    (2) reject(Runnable)

    reject(Runnable)直接委托给拒绝策略handler调用rejectedExecution方法。

    handler是实现RejectedExecutionHandler接口的对象,表示线程池饱和时的饱和策略rejectedExecution是此接口的唯一方法,它一般在构造方法中指定。

        final void reject(Runnable command) {
            handler.rejectedExecution(command, this);
        }

    7) shutdown系列方法

    (1) shutdown()

    shutdown()方法是用来关闭线程池执行器的,它的主要逻辑是:

    先将runState至少设为SHUTDOWN级,然后中断池中的空闲线程,调用onShutdown空方法(钩子函数,留给子类实现),最后检查runState是否应转为TERMINATED状态及与之相关的处理。

    public void shutdown() {
        final ReentrantLock mainLock = this.mainLock;
        mainLock.lock();//先获取锁
        try {
            checkShutdownAccess();//检查权限
            advanceRunState(SHUTDOWN);//若runState已至少是STOP级就不做任何处理,反之将runState设为STOP,
            interruptIdleWorkers();//中断池中的空闲线程
            //空方法,留后子类实现,它是一个钩子函数   其子类ScheduledThreadPoolExecutor重写了此方法
            onShutdown(); // hook for ScheduledThreadPoolExecutor 
        } finally {
            mainLock.unlock();
        }
        tryTerminate();//检查runState是否应转为TERMINATED状态及与之相关的处理
    }
    shutdown

    (2) shutdownNow()

    shutdownNow()方法是用来立即关闭线程池执行器的,它的主要逻辑是:

    先将runState至少设为STOP级,然后中断所有已启动的线程,再从任务队列中移除所有待执行的任务,再然后检查runState是否应转为TERMINATED状态及与之相关的处理,最后返回这些待执行的任务列表。

    可以看出shutdownshutdownNow之间的区别在于:

    ①shutdown将runState至少设为SHUTDOWN,而shutdownNow将runState至少设为STOP.
    ②shutdown只中断空闲线程,而shutdownNow会中断所有线程。换而言之,shutdown不去停止正在执行的任务,而shutdownNow会让正在执行的任务(如果任务能响应中断的话)停止。
    ③shutdown不去任务队列中移除任务,而shutdownNow会从任务队列中移除所有的任务。换而言之,shutdown之前提交的任务还能被执行,而shutdownNow之前提交的任务不能被执行了。

        public List<Runnable> shutdownNow() {
            List<Runnable> tasks;
            final ReentrantLock mainLock = this.mainLock;
            mainLock.lock();//先获取锁
            try {
                checkShutdownAccess();//检查权限
                advanceRunState(STOP);//若runState>STOP就不做任何处理,反之将runState设为STOP,
            //中断所有已启动的线程(包括正在执行任务的非空闲线程和等待任务的空闲线程),不响应中断的任务可能无法被终止
                interruptWorkers();
                tasks = drainQueue();//从队列中移除所有任务
            } finally {
                mainLock.unlock();
            }
            tryTerminate();//检查runState是否应转为TERMINATED状态及与之相关的处理
            return tasks;
        }
    shutdownNow

    shutdownNow()方法体中调用drainQueue()从队列中移除所有任务, 我们来看看drainQueue()如何做的。

    ① drainQueue()

    drainQueue所实现的逻辑很简单:它只将将工作队列中的所有任务移除,并将这些任务返回。

        private List<Runnable> drainQueue() {
            BlockingQueue<Runnable> q = workQueue;
            ArrayList<Runnable> taskList = new ArrayList<Runnable>();
            q.drainTo(taskList);//BlockingQueue的drainTo方法会一次性取出所有可用元素,在取出后会在队列中删除这些元素。
            if (!q.isEmpty()) {//DelayQueue等类型的队列直接出队可能失败,再次用remove方法获取之前出队失败的元素。
                for (Runnable r : q.toArray(new Runnable[0])) {
                    if (q.remove(r))
                        taskList.add(r);
                }
            }
            return taskList;
        }
    drainQueue

    (3) isShutdown()

    isShutdown()返回线程池执行器是否被关闭的布尔值。从方法实现上可以看出,它是根据runState的值判断线程池执行器是否被关闭,只要runState不小于SHUTDOWN,执行器就是关闭状态。

    public boolean isShutdown() {
        return ! isRunning(ctl.get());
    }
    private static boolean isRunning(int c) {
        return c < SHUTDOWN;
    }

    8) 配置相关setter/getter

    (1) ThreadFactory

    setThreadFactory/getThreadFactory用于设置/获取线程工厂,只要实现ThreadFactory接口就可以自定义线程工厂。

    public void setThreadFactory(ThreadFactory threadFactory) {
        if (threadFactory == null)
            throw new NullPointerException();
        this.threadFactory = threadFactory;
    }
    public ThreadFactory getThreadFactory() {
        return threadFactory;
    }
    View Code

    (2) RejectedExecutionHandler

    setRejectedExecutionHandler/getRejectedExecutionHandler用于设置/获取饱和策略,当线程池和队列均已满时,调用RejectedExecutionHandler.rejectedExecution处理新任务。

    public void setRejectedExecutionHandler(RejectedExecutionHandler handler) {
        if (handler == null)
            throw new NullPointerException();
        this.handler = handler;
    }
    public RejectedExecutionHandler getRejectedExecutionHandler() {
        return handler;
    }
    View Code

    (3) CorePoolSize

    setCorePoolSize/getCorePoolSize用于设置/获取核心线程数

        public void setCorePoolSize(int corePoolSize) {
            if (corePoolSize < 0)
                throw new IllegalArgumentException();
            int delta = corePoolSize - this.corePoolSize;
            this.corePoolSize = corePoolSize;//更新corePoolSize属性
            //如果实际线程数已经多于最新的corePoolSize,就中断所有空闲线程。
            if (workerCountOf(ctl.get()) > corePoolSize)
                interruptIdleWorkers();
            //“当前实际线程数少于新corePoolSize”且"新corePoolSize大于原来的corePoolSize" 时
              //就预先启动足够的新worker线程(最大为新的corePoolSize)以处理队列中的当前任务数,
            //但是如果在添加worker过程中队列变为空则停止添加。
            else if (delta > 0) { 
                // We don't really know how many new threads are "needed".
                // As a heuristic, prestart enough new workers (up to new
                // core size) to handle the current number of tasks in
                // queue, but stop if queue becomes empty while doing so.
                int k = Math.min(delta, workQueue.size());
                while (k-- > 0 && addWorker(null, true)) {
                    if (workQueue.isEmpty())
                        break;
                }
            }
        }
        public int getCorePoolSize() {
            return corePoolSize;
        }
    View Code

    prestartCoreThread()方法启动一个核心线程,若所有核心线程已启动则返回false.
    ensurePrestart()方法与prestartCoreThread()类似,但它能保证池中至少有一个线程。
    prestartAllCoreThreads()方法将一次性启动所有核心线程,若所有核心线程已启动将返回0。

    public boolean prestartCoreThread() {
        //当前线程数小于corePoolSize就创建一个核心线程
        return workerCountOf(ctl.get()) < corePoolSize &&
            addWorker(null, true);
    }
    
    void ensurePrestart() {
        int wc = workerCountOf(ctl.get());
        if (wc < corePoolSize)
            //当前线程数小于corePoolSize创建一个核心线程
            addWorker(null, true);
        else if (wc == 0)
            //corePoolSize为0,当前线程数也为0,就创建一个非核心线程。池中至少有这个刚启动的线程了
            addWorker(null, false);
    }
    public int prestartAllCoreThreads() {
        int n = 0;
        while (addWorker(null, true))//一次性启动所有核心线程
            ++n;
        return n;//返回此方法启动的核心线程数
    }

    (4) MaximumPoolSize

    setMaximumPoolSize/getMaximumPoolSize用于设置/获取最大可允许创建的线程数

        public void setMaximumPoolSize(int maximumPoolSize) {
            if (maximumPoolSize <= 0 || maximumPoolSize < corePoolSize)
                throw new IllegalArgumentException();
            this.maximumPoolSize = maximumPoolSize;//更新maximumPoolSize属性
            //若当前实际的线程数多于新的maximumPoolSize,就中断所有空闲线程
            if (workerCountOf(ctl.get()) > maximumPoolSize)
                interruptIdleWorkers();
        }
        public int getMaximumPoolSize() {
            return maximumPoolSize;
        }
    View Code

    (5) KeepAliveTime

    setKeepAliveTime/setKeepAliveTime用来设置/获取线程的最大空闲时间。

       public void setKeepAliveTime(long time, TimeUnit unit) {
            if (time < 0)
                throw new IllegalArgumentException();
            if (time == 0 && allowsCoreThreadTimeOut())
                throw new IllegalArgumentException("Core threads must have nonzero keep alive times");
            long keepAliveTime = unit.toNanos(time);
            long delta = keepAliveTime - this.keepAliveTime;
            this.keepAliveTime = keepAliveTime;//更新maximumPoolSize属性
            if (delta < 0)//新的keepAliveTime小于原keepAliveTime,就中断所有空闲线程
                interruptIdleWorkers();
        }
        //处理KeepAliveTime的时间单位转换 
        public long setKeepAliveTime(TimeUnit unit) {
            return unit.convert(keepAliveTime, TimeUnit.NANOSECONDS);
        }
       public long getKeepAliveTime(TimeUnit unit) {
            return unit.convert(keepAliveTime, TimeUnit.NANOSECONDS);
        }
    View Code

     默认情况下keepAliveTime,只适用于非核心线程,即核心线程不会因空闲等待太久而被终止, 但使用allowCoreThreadTimeOut()方法并将参数设为true就可改变这种默认效果,使keepAliveTime对核心线程同样有效。

       public boolean allowsCoreThreadTimeOut() {
            return allowCoreThreadTimeOut;
        }
        public void allowCoreThreadTimeOut(boolean value) {
            if (value && keepAliveTime <= 0)
                throw new IllegalArgumentException("Core threads must have nonzero keep alive times");
            if (value != allowCoreThreadTimeOut) {
                allowCoreThreadTimeOut = value;//更新allowCoreThreadTimeOut属性
                if (value)//若允许核心线程超时,就中断所有空闲线程
                    interruptIdleWorkers();
            }
        }

    (6) WorkQueue

    getQueue用于获取任务队列。

    public BlockingQueue<Runnable> getQueue() {
        return workQueue;
    }

    9) 状态监控相关方法

    (1) getPoolSize()

    getPoolSize()返回当前线程池中的工作线程总数

        public int getPoolSize() {
            final ReentrantLock mainLock = this.mainLock;
            mainLock.lock();
            try {
                // Remove rare and surprising possibility of
                // isTerminated() && getPoolSize() > 0
                //若runState是TIDYING或TERMINATED时,workerCount一定为0(之前在tryTerminate中分析过)
                //反之就取workers.size()
                return runStateAtLeast(ctl.get(), TIDYING) ? 0
                    : workers.size();
            } finally {
                mainLock.unlock();
            }
        }
    getPoolSize

    (2) getActiveCount()

    getActiveCount() 返回当前活动(正在执行任务)的工作线程数

        public int getActiveCount() {
            final ReentrantLock mainLock = this.mainLock;
            mainLock.lock();
            try {
                int n = 0;
                for (Worker w : workers)
                    if (w.isLocked())//Worker锁被持有,表示正在执行任务
                        ++n;
                return n;
            } finally {
                mainLock.unlock();
            }
        }
    View Code

    (3) getLargestPoolSize()

    getLargestPoolSize()返回曾经创建过的最大线程数。通过这个数据可以知道线程池是否曾经满过。如该数值等于线程池的最大大小,则表示线程池曾经满过。

        public int getLargestPoolSize() {
            final ReentrantLock mainLock = this.mainLock;
            mainLock.lock();
            try {
                return largestPoolSize;
            } finally {
                mainLock.unlock();
            }
        }
    View Code

    (4) getTaskCount()

    getTaskCount()返回执行器从启动到现在所接受的任务总数。

        public long getTaskCount() {
            final ReentrantLock mainLock = this.mainLock;
            mainLock.lock();
            try {
                long n = completedTaskCount;//先获取表示完成的任务数的成员变量completedTaskCount
                for (Worker w : workers) {
                //还有一些记录有worker中的已完成任务数(尚未同步到completedTaskCount中)
                    n += w.completedTasks;
                    //另外还要加上正在执行的任务(还未完成)
                    if (w.isLocked())//此worker正在执行任务
                        ++n;
                }
                return n + workQueue.size();//最后加上任务队列中的任务数
            } finally {
                mainLock.unlock();
            }
        }
    View Code

    (5) getCompletedTaskCount()

    getCompletedTaskCount() 返回执行器完成的任务总数。

    public long getCompletedTaskCount() {
        final ReentrantLock mainLock = this.mainLock;
        mainLock.lock();
        try {
            long n = completedTaskCount;//先获取表示完成的任务数的成员变量completedTaskCount
            for (Worker w : workers)
                //还有一些记录有worker中的已完成任务数(尚未同步到completedTaskCount中)
                n += w.completedTasks;
            return n;
        } finally {
            mainLock.unlock();
        }
    }
    getCompletedTaskCount

    (6) 空实现的钩子函数

    除此之外,线程池还提供了3个空方法,beforeExecute方法在执行一个任务前被调用,afterExecute方法在一个任务完成后被调用,terminated()方法在线程池停止时被调用。
    我们可继承ThreadPoolExecutor来实现自己的线程池,并以此为基础重写这3个方法来实现自己的监控逻辑。

    10) finalize()

    finalize()方法是顶级父类Object的方法,此方法在对象被GC回收前调用,一般用来清理释放占用的资源。ThreadPoolExecutor重写了此方法,其核心逻辑是调用shutdown()方法关闭执行器。

    protected void finalize() {
        SecurityManager sm = System.getSecurityManager();
        if (sm == null || acc == null) {
            shutdown();
        } else {
            PrivilegedAction<Void> pa = () -> { shutdown(); return null; };
            AccessController.doPrivileged(pa, acc);
        }
    }

    7 工作流程

    以sumbit(Runnable/Callable)方法为例,说明线程池执行器ThreadPoolExecutor的主要工作流程。

    sumbit(Runnable/Callable)在父类AbstractExecutorService中已有基本实现,但其核心逻辑execute方法仍要子类实现,所以ThreadPoolExecutor实现了excute方法。

    submit(Runnable/Callable)方法的主要工作流程:

    ①它先将Runnable/Callable任务统一封装成FutureTask。那么FutureTask是如何封装原始任务的? FutureTask将Runnable或Callable任务设为它的(若原任务的类型是Runnable就使用适配器模式将其适配为Callable类型)Callable类型属性callable;另外FutureTask也实现了Runnable接口,而它的run()方法核心内容就是执行callable.call、并记录任务结果或任务执行发生的异常信息

    ②然后执行execute(task)的核心逻辑是addWorker(), addWorker()会启动一个新的工作线程,即worker.thread启动。worker.thread线程启动后,worker.thread线程将执行worker.run()方法,而worker.run()方法又委托给外部类ThreadPoolExecutor的runWorker方法实现。

    ③runWorker基本逻辑是:循环往复从worker.firstTask或工作队列中获取并执行任务 。若获取的任务为空,此线程不再执行任务,worker.run方法将结束,此线程即将终止。若获取到任务不为空就调用FutureTask.run执行任务. 这里的FutureTask.run执行会FutureTask.callable.call()并记录任务结果或发生的异常。这里的callable.call()才是最原始的任务执行内容。

    
    
  • 相关阅读:
    CodeForces 757C Felicity is Coming!(排列组合)
    Ural 1519 Formula 1( 插头dp )
    FZU 2187 回家种地 ( 扫描线 + 离散 求矩阵单次覆盖面积 )
    HDU 1255 覆盖的面积 ( 扫描线 + 离散 求矩阵大于k次面积并 )
    ZOJ 3841 Cards
    HDU 4012 Paint on a Wall(状压+bfs)
    Topcoder SRM653div2
    2015 GDUT校赛
    Topcoder SRM652div2
    CodeChef A String Game(SG)
  • 原文地址:https://www.cnblogs.com/gocode/p/fully-analysis-source-code-of-ThreadPoolExecutor.html
Copyright © 2020-2023  润新知