Concurrent -- 01 -- ThreadPoolExecutor解析

原文链接:Concurrent – 01 – ThreadPoolExecutor解析


相关文章:


在项目开发过程中,服务端会接收请求并进行处理,当请求数量不大时,我们可以为每个请求都分配一个线程,而当请求数量很大时,如果还是为每个请求都分配一个线程的话,会导致频繁地创建和销毁线程,从而大大降低了系统的效率,这个时候,线程池便派上了用场,通过对线程的重复使用,大大地提高了系统的效率

总的来说,线程池的优点可以归纳为以下几点

  • 降低资源消耗

    • 通过重复利用已创建的线程降低线程创建和销毁造成的消耗
  • 提高响应速度

    • 当任务达到时,可以不需要等待新的线程创建就能立即执行
  • 提高线程的可管理性

    • 线程是稀缺资源,如果无限制地创建,不仅会消耗系统资源,还会降低系统的稳定性,使用线程池可以进行统一的分配、调优和监控

在线程池中,ThreadPoolExecutor 类是最核心的一个类,想要透彻地了解线程池,则必须先了解这个类,在此之前,我们先来看下线程池的类图

在这里插入图片描述


一、Executor 接口

  • Executor 接口只有一个 execute(Runnable command) 方法,传入 Runnable 参数,用于执行任务

    public interface Executor {
    
        void execute(Runnable command);
    }
    

二、ExecutorService 接口

  • ExecutorService 接口继承自 Executor 接口,并新增了 shutdown()、shutdownNow()、isShutdown()等一系列方法

    public interface ExecutorService extends Executor {
    
        void shutdown();
    
        List<Runnable> shutdownNow();
    
        boolean isShutdown();
    
        boolean isTerminated();
    
        boolean awaitTermination(long timeout, TimeUnit unit)
            throws InterruptedException;
    
        <T> Future<T> submit(Callable<T> task);
    
        <T> Future<T> submit(Runnable task, T result);
    
        Future<?> submit(Runnable task);
    
        <T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks)
            throws InterruptedException;
    
        <T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks,
                                      long timeout, TimeUnit unit)
            throws InterruptedException;
    
        <T> T invokeAny(Collection<? extends Callable<T>> tasks)
            throws InterruptedException, ExecutionException;
    
        <T> T invokeAny(Collection<? extends Callable<T>> tasks,
                        long timeout, TimeUnit unit)
            throws InterruptedException, ExecutionException, TimeoutException;
    }
    
    

三、AbstractExecutorService 抽象类

  • AbstractExecutorService 抽象类实现了 ExecutorService 接口,并提供了一些方法的默认实现,如:submit()、invokeAny()、invokeAll() 等方法

四、ThreadPoolExecutor 类

  • 1、参数解析

    • 首先我们来看下 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;
      }
      
    • 由源码可知,ThreadPoolExecutor 类的构造函数共有七个参数,它们的具体作用分别如下

      • corePoolSize

        • 核心线程数

        • 线程池启动后默认是空的,只有当任务来临时才会创建线程进行处理

        • 当核心线程空闲时,会一直等待新的任务,而不会被销毁回收

        • 相关方法

          • prestartCoreThread()

            • 预先创建一个核心线程,返回 true

            • 此方法会覆盖在执行新任务时,创建核心线程的默认策略

            • 如果此前所有的核心线程都已被创建,则调用该方法返回 false

          • prestartAllCoreThreads()

            • 预先创建所有核心线程

            • 此方法会覆盖在执行新任务时,创建核心线程的默认策略

      • maximumPoolSize

        • 最大线程数

        • 当 workQueue 使用无界队列 (如:没有设置 capacity 的 LinkedBlockingQueue) 时,此参数无效

      • keepAliveTime

        • 非核心线程的最大存活时间

        • 当非核心线程空闲时间超过最大存活时间时,则会被销毁回收

        • 相关方法

          • allowCoreThreadTimeOut(boolean value)

            • 设置是否允许核心线程超时
          • allowsCoreThreadTimeOut()

            • 获取核心线程是否可以超时的标识
      • unit

        • keepAliveTime 参数的时间单位

        • 一共有七种枚举常量,如下所示

          常量名 含义
          NANOSECONDS 纳秒,等于 $1 * 10^{-9}s$
          MICROSECONDS 微秒,等于 $1 * 10^{-6}s$
          MILLISECONDS 毫秒,等于 $1 * 10^{-3}s$
          SECONDS
          MINUTES
          HOURS
          DAYS
      • workQueue

        • 工作队列

        • 当线程池中线程数量达到核心线程数,且都处于活跃状态时,会将新提交的任务放入队列中,等待空闲的线程来获取处理

      • threadFactory

        • 线程创建工厂

        • 创建线程或线程池时尽量指定有意义的线程名称,方便出错时回溯

        • 创建线程池的时候,尽量使用带有 ThreadFactory 的构造函数,并提供自定义的 ThreadFactory 实现或者使用第三方实现

      • handler

        • 线程拒绝策略

        • 一共有四种线程拒绝策略,如下所示

          拒绝策略 含义
          AbortPolicy 直接丢弃任务,抛出异常 (默认策略)
          CallerRunsPolicy 将任务分配给调用线程来执行
          DiscardPolicy 直接丢弃任务,不抛出异常
          DiscardOldestPolicy 丢弃队列中最早的任务,不抛出异常

  • 2、线程池状态

    • 线程池有五大状态,分别是:RUNNING、SHUTDOWN、STOP、TIDYING、TERMINATED

      • RUNNING (-1)

        • 接受新任务并处理排队任务
      • SHUTDOWN (0)

        • 不接受新任务,但会处理排队任务

        • 当线程处于 RUNNING 状态时,调用 shutdown() 方法会使线程池进入到该状态

      • STOP (1)

        • 不接受新任务,也不处理排队任务,同时会中断正在处理的任务
      • TIDYING (2)

        • 所有任务都已终止,workerCount (有效线程数) 为零

        • 当线程池进入到该状态时,会调用 terminated() 方法

      • TERMINATED (3)

        • terminated() 方法执行完毕后进入该状态

  • 3、源码解析

    • 线程池状态

      private final AtomicInteger ctl = new AtomicInteger(ctlOf(RUNNING, 0));
      // 29位
      private static final int COUNT_BITS = Integer.SIZE - 3;
      // 线程池最大容量
      private static final int CAPACITY   = (1 << COUNT_BITS) - 1;
      
      // runState is stored in the high-order bits
      // 线程池运行状态
      // 111 + 29个0
      private static final int RUNNING    = -1 << COUNT_BITS;
      // 000 + 29个0
      private static final int SHUTDOWN   =  0 << COUNT_BITS;
      // 001 + 29个0
      private static final int STOP       =  1 << COUNT_BITS;
      // 010 + 29个0
      private static final int TIDYING    =  2 << COUNT_BITS;
      // 011 + 29个0
      private static final int TERMINATED =  3 << COUNT_BITS;
      
      // Packing and unpacking ctl
      // 获取线程池运行状态
      private static int runStateOf(int c)     { return c & ~CAPACITY; }
      // 获取线程池中线程数目
      private static int workerCountOf(int c)  { return c & CAPACITY; }
      // 反向构造 ctl 的值,初始值为 ctlOf(RUNNING, 0)
      private static int ctlOf(int rs, int wc) { return rs | wc; }
      
      • ctl

        • 一个 32 位的 int 值,用于表示线程池的运行状态 (runState) 和线程池中的线程数目 (workerCount)

          概念 含义
          runState 占据 ctl 的高 3 位,表示线程池的运行状态
          workerCount 占据 ctl 的低 29 位,表示线程池中的线程数目
      • COUNT_BITS

        • 表示 29 位
      • CAPACITY

        • 线程池最大容量 (2^29 - 1)
      • runStateOf(int c)

        private static int runStateOf(int c)     { return c & ~CAPACITY; }
        
        • 获取线程池运行状态

        • c 代表 ctl 的值,将其与 ~CAPACITY (111 00000 00000000 00000000 00000000) 进行 & 操作,c 的低 29 位与 ~CAPACITY 的低 29 位 00000 00000000 00000000 00000000 进行 & 操作,无论 c 的低 29 位为何值,与 00000 00000000 00000000 00000000 进行 & 操作后都会变为 00000 00000000 00000000 00000000,也就是舍弃了 c 的低 29 位;而 c 的高 3 位与 ~CAPACITY 的高 3 位 111 进行 & 操作,c 的高 3 位还是会保持原值,这样我们就从 c 中解析出了 runState 的值

      • workerCountOf(int c)

        private static int workerCountOf(int c)  { return c & CAPACITY; }
        
        • 获取线程池中线程数目

        • c 代表 ctl 的值,将其与 CAPACITY 进行 & 操作,也就是与 000 11111 11111111 11111111 11111111 进行 & 操作,c 的高 3 位与 CAPACITY 的高 3 位 000 进行 & 操作,无论 c 的高 3 位为何值,与 000 进行 & 操作后都会变为 000,也就是舍弃了 c 的高 3 位值;而 c 的低 29 位与 CAPACITY 的低 29 位 11111 11111111 11111111 11111111 进行 & 操作,c 的低 29 位还是会保持原值,这样我们就从 c 中解析出了 workerCount 的值

        • 线程池状态的常量可以通过值的大小来表示先后关系,如:rs >= SHUTDOWN 可用于表示线程的状态可能是 SHUTDOWN 或 STOP 或 TIDYING 或 TERMINATED,而不可能是 RUNNING

      • ctlOf(int rs, int wc)

        private static int ctlOf(int rs, int wc) { return rs | wc; }
        
        • 反向构造 ctl 的值,初始值为 ctlOf(RUNNING, 0)

        • rs 表示线程池的运行状态 (runState),其高 3 位有值,低 29 位全部为 0;wc 表示线程池中的线程数目 (workerCount),其高 3 为全部为 0,低 29 位有值

        • 将 rs 与 wc 进行 | 操作,即用 rs 的高 3 位与 wc 的低 29 位填充成一个新的 int 值 (即 ctl 的值)


    • Worker

      // 继承自 AbstractQueuedSynchronizer (AQS),实现了锁控制
      private final class Worker
          extends AbstractQueuedSynchronizer
          implements Runnable
      {
          // Worker 类永远不会被序列化,但提供了一个 serialVersionUID 来避免编译警告
          private static final long serialVersionUID = 6138294804551838833L;
      
          // Worker 运行所在的工作线程 (由线程工厂创建,如果创建失败,则为 null)
          final Thread thread;
          // 工作线程要执行的初始任务,可能为 null
          Runnable firstTask;
          // 工作线程完成的任务数量
          volatile long completedTasks;
      
           // 使用给定的第一个任务和线程工厂创建的线程来构造 Worker
          Worker(Runnable firstTask) {
              // 限制线程直到 runWorker() 方法执行之前都不允许被打断
              setState(-1);
              this.firstTask = firstTask;
              // 使用线程工厂创建线程
              this.thread = getThreadFactory().newThread(this);
          }
      
          public void run() {
              // 调用外部的 runWorker() 方法
              runWorker(this);
          }
      
          // 判断线程是否获得了独占锁 0=未获得 1=获得
          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) {
              // 设置当前拥有独占访问权限的线程 (null)
              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) {
                  }
              }
          }
      }
      
      • 线程池中每一个线程都被封装成了一个 Worker 对象,线程池维护的其实就是一组 Worker 对象

      • Worker 类继承自 AQS,并实现了 Runnable 接口,两个关键参数 threadfirstTask

        • thread

          • 工作线程,由线程工厂 (ThreadFactory) 创建,用于处理任务
        • firstTask

          • 工作线程要执行的初始任务,即在构造方法中传入的任务
      • 在 Worker 类的构造方法中,会通过 getThreadFactory().newThread(this) 来新建一个线程,其中 this 表示的是当前对象,也就是 Worker 对象,由于 Worker 本身实现了 Runnable 接口,是一个线程,所以当一个 Worker 对象启动时,会调用自身的 run() 方法

      • Worker 类使用 AQS 来实现独占锁的功能


    • addWorker(Runnable firstTask, boolean core)

      private boolean addWorker(Runnable firstTask, boolean core) {
          retry:
          for (;;) {
              int c = ctl.get();
              // 获取线程池运行状态
              int rs = runStateOf(c);
      
              /*
               * 如果线程池运行状态(rs) >= SHUTDOWN,则表示队列不再接收新的任务,
               * 满足该条件后,再判断后续的3个条件,只有有1个不满足就返回false,
               * 则if判断为true,返回false,方法执行结束,表示不需要添加新的工作线程
               *      1、rs == SHUTDOWN
               *          线程池为SHUTDOWN状态,不再接受新任务,但会处理排队任务
               *      2、firstTask == null
               *          工作线程执行的初始任务为null
               *      3、! workQueue.isEmpty()
               *          工作队列不为空
               */
              if (rs >= SHUTDOWN &&
                  ! (rs == SHUTDOWN &&
                     firstTask == null &&
                     ! workQueue.isEmpty()))
                  return false;
      
              for (;;) {
                  // 获取工作线程数
                  int wc = workerCountOf(c);
                  /*
                   * 如果工作线程数(wc) >= 线程池最大容量(CAPACITY),则返回false;
                   * 这里的core为addWorker()方法的第二个参数
                   *      1、true,表示根据核心线程数(corePoolSize)来判断
                   *      2、false,表示根据最大线程数(maximumPoolSize)来判断
                   * 如果工作线程数(wc) >= 核心线程数(corePoolSize)/最大线程数(maximumPoolSize),则返回false
                   */
                  if (wc >= CAPACITY ||
                      wc >= (core ? corePoolSize : maximumPoolSize))
                      return false;
                  /*
                   * 尝试增加线程池中线程数目(workerCount),
                   * 如果成功,则跳出外层循环retry
                   */
                  if (compareAndIncrementWorkerCount(c))
                      break retry;
                  // 如果增加线程失败,则重新获取ctl的值
                  c = ctl.get();
                  /*
                   * 重新获取线程池运行状态吗,并与先前获取的线程池运行状态(rs)相比较,
                   * 如果不相等,则说明线程池状态已被改变,返回外层循环继续执行
                   */
                  if (runStateOf(c) != rs)
                      continue retry;
                  // else CAS failed due to workerCount change; retry inner loop
              }
          }
      
          // 标记工作线程是否已启动
          boolean workerStarted = false;
          // 标记工作线程是否被添加
          boolean workerAdded = false;
          Worker w = null;
          try {
              // 根据firstTask构建Worker对象
              w = new Worker(firstTask);
              // 获取Worker中的工作线程
              final Thread t = w.thread;
              if (t != null) {
                  final ReentrantLock mainLock = this.mainLock;
                  mainLock.lock();
                  try {
                      // 获取线程池运行状态
                      int rs = runStateOf(ctl.get());
      
                      /*
                       * 如果线程池运行状态(rs) < SHUTDOWN(即为RUNNING状态)或
                       * 如果线程池运行状态(rs)为SHUTDOWN状态且初始任务(firstTask)为null,
                       * 则向线程池中添加线程(线程池状态为SHUTDOWN时,虽然不会再接受新任务,
                       * 但仍然会处理排队任务)
                       */
                      if (rs < SHUTDOWN ||
                          (rs == SHUTDOWN && firstTask == null)) {
                          // 检测工作线程是否处于活动状态
                          if (t.isAlive()) // precheck that t is startable
                              throw new IllegalThreadStateException();
                          // 如果工作线程不处于活动状态,则向workers(HashSet)中添加Worker
                          workers.add(w);
                          // 获取workers的大小
                          int s = workers.size();
                          /*
                           * largestPoolSize
                           *      用于记录线程池中出现过的最大线程数量
                           * 如果workers的大小(s) > largestPoolSize
                           * 则将workers的大小(s)赋值给largestPoolSize
                           */
                          if (s > largestPoolSize)
                              largestPoolSize = s;
                          // 将工作线程添加标识设为true
                          workerAdded = true;
                      }
                  } finally {
                      mainLock.unlock();
                  }
                  /*
                   * 如果工作线程已被添加,
                   * 则启动工作线程,并将工作线程启动标识设为true
                   */
                  if (workerAdded) {
                      t.start();
                      workerStarted = true;
                  }
              }
          } finally {
              // 如果工作线程未被启动,则回滚工作线程的创建
              if (! workerStarted)
                  addWorkerFailed(w);
          }
          return workerStarted;
      }
      
      • addWorker() 方法主要用于在线程池中创建一个新的线程来执行任务,其有两个参数 firstTaskcore

        • firstTask

          • 工作线程要执行的初始任务,即在构造方法中传入的任务
        • core

          • 为 true 时,表示在新增线程时,会判断当前活动线程数是否小于核心线程数 (corePoolSize)

          • 为 false 时,表示在新增线程时,会判断当前活动线程数是否小于最大线程数 (maximumPoolSize)


    • runWorker(Worker w)

      final void runWorker(Worker w) {
          // 获取当前线程
          Thread wt = Thread.currentThread();
          // 获取初始任务
          Runnable task = w.firstTask;
          w.firstTask = null;
          w.unlock(); // allow interrupts
          boolean completedAbruptly = true;
          try {
              // 循环获取任务
              while (task != null || (task = getTask()) != null) {
                  w.lock();
                  /*
                   * 如果线程池状态 >= STOP(即为TIDYING、TERMINATED状态)
                   * 且当前线程未被中断,则中断当前线程
                   *
                   * 如果在执行if语句期间,执行了shutdownNow()方法,shutdownNow()方法
                   * 会将线程池中所有线程的状态设置为STOP,此时调用Thread.interrupted()
                   * 来确保当前线程为非中断状态(interrupted()方法会清除当前线程的中断标识),
                   * 且此时线程池状态 >= STOP(即为TIDYING、TERMINATED状态)
                   * 且当前线程未被中断(已被interrupted()方法复位),则中断当前线程
                   */
                  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;
                      // 统计当前worker完成了多少任务
                      w.completedTasks++;
                      w.unlock();
                  }
              }
              completedAbruptly = false;
          } finally {
              /*
               * 线程结束时调用,做一些收尾工作
               * 如:将worker从workers中移除、统计任务完成个数等
               */
              processWorkerExit(w, completedAbruptly);
          }
      }
      
      • runWorker() 方法主要用于执行任务

    • getTask()

      private Runnable getTask() {
          // 标记上次从工作队列中获取任务是否超时
          boolean timedOut = false;
      
          for (;;) {
              int c = ctl.get();
              // 获取线程池运行状态
              int rs = runStateOf(c);
      
              /*
               * 如果线程池状态(rs) >= SHUTDOWN(即为非RUNNING状态),再进行以下判断
               *      1、线程池状态(rs)是否 >= STOP(即为STOP、TIDYING、TERMINATED状态)
               *      2、工作队列(workQueue)是否为空
               */
              if (rs >= SHUTDOWN && (rs >= STOP || workQueue.isEmpty())) {
                  // 将线程池中线程数目-1,并返回null
                  decrementWorkerCount();
                  return null;
              }
      
              // 获取线程池中线程数目
              int wc = workerCountOf(c);
      
              /*
               * timed用于标记是否需要进行超时控制
               *      1、allowCoreThreadTimeOut
               *          是否允许核心线程超时,默认为false
               *      2、线程池中线程数目(wc) > 核心线程数(corePoolSize)
               *          当线程池中线程数目大于核心线程数时,
               *          需要对非核心线程进行超时控制
               */
              boolean timed = allowCoreThreadTimeOut || wc > corePoolSize;
      
              /*
               * 如果线程池中线程数目(wc) > 最大线程数(maximumPoolSize)或
               * timed && timedOut(即当前操作需要进行超时控制且上次从工作队列中获取任务失败),
               * 满足上述条件之一后,再进行判断后续条件
               * 如果线程池中线程数目(wc) > 1或工作队列(workQueue)为空,则满足条件
               */
              if ((wc > maximumPoolSize || (timed && timedOut))
                  && (wc > 1 || workQueue.isEmpty())) {
                  // 尝试将线程池中线程数目-1,并返回null,如果失败,则返回重试
                  if (compareAndDecrementWorkerCount(c))
                      return null;
                  continue;
              }
      
              try {
                  /*
                   * 如果timed为true,则表示需要对工作队列(workQueue)的poll()
                   * 方法进行超时控制,如果在keepAliveTime时间内没有获取到任务,则返回null;
                   * 如果为false,则表示通过工作队列(workQueue)的take()方法来获取任务,
                   * 若此时工作队列为空,则take()方法会进行阻塞,直到工作队列不为空,可获得任务为止
                   */
                  Runnable r = timed ?
                      workQueue.poll(keepAliveTime, TimeUnit.NANOSECONDS) :
                      workQueue.take();
                  if (r != null)
                      return r;
                  timedOut = true;
              } catch (InterruptedException retry) {
                  timedOut = false;
              }
          }
      }
      
      • getTask() 方法主要用于从工作队列中获取任务

    • execute(Runnable command)

      public void execute(Runnable command) {
          if (command == null)
              throw new NullPointerException();
      
          int c = ctl.get();
          /*
           * 如果线程池中线程数目小于核心线程数(corePoolSize),
           * 则新建一个线程放入线程池中,用于执行任务
           */
          if (workerCountOf(c) < corePoolSize) {
              /*
               * 往线程池中添加线程,其中第二个参数用于限制
               * 添加线程的数量是根据核心线程数(corePoolSize)来判断,
               * 还是根据最大线程数(maxPoolSize)来判断
               *      1、true,表示根据核心线程数(corePoolSize)来判断
               *      2、false,表示根据最大线程数(maxPoolSize)来判断
               */
              if (addWorker(command, true))
                  return;
              c = ctl.get();
          }
          // 如果当前线程池是RUNNING状态,且往队列中添加任务成功
          if (isRunning(c) && workQueue.offer(command)) {
              // 重新获取ctl的值
              int recheck = ctl.get();
              /*
               * 再次判断线程池的状态是否为RUNNING状态,
               * 如果不是,则移除之前添加进队列的任务,
               */
              if (! isRunning(recheck) && remove(command))
                  // 使用线程拒绝策略对任务进行处理
                  reject(command);
              // 获取线程池中线程数量,并判断其是否等于0
              else if (workerCountOf(recheck) == 0)
                  // 往线程池中添加线程,但不执行
                  addWorker(null, false);
          }
          /*
           * 往线程池中添加线程,添加线程时根据最大线程数(maxPoolSize)来判断
           * 如果添加失败,则使用线程拒绝策略对任务进行处理
           */
          else if (!addWorker(command, false))
              reject(command);
      }
      
      • execute() 方法主要用于提交任务,交由工作线程来进行处理

      • 任务执行流程

        在这里插入图片描述

        • 当线程池接收到新任务时,先判断当前线程数量是否小于核心线程数 (corePoolSize),如果小于,则即使其他线程都处于空闲状态,也会创建新的线程 (核心线程) 来处理新任务

        • 如果当前线程数量大于或等于核心线程数 (corePoolSize),则再判断工作队列 (workQueue) 是否有空位,如果有,则将新任务添加到工作队列 (workQueue) 中,等待空闲线程去获取处理

        • 如果工作队列 (workQueue) 没有空位,则再判断当前线程数量是否小于最大线程数 (maximumPoolSize),如果小于,则会创建新的线程 (非核心线程) 来处理任务

        • 如果当前线程数量大于或等于最大线程数 (maximumPoolSize),则使用线程拒绝策略来处理新任务


五、参考资料

posted @ 2020-05-17 22:15  GeneXu  阅读(60)  评论(0)    收藏  举报