线程池执行器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()才是最原始的任务执行内容。

 

 

 

 


posted @ 2020-03-31 00:19  蜀中孤鹰  阅读(589)  评论(1编辑  收藏  举报