Concurrent -- 01 -- ThreadPoolExecutor源码解析

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


相关文章:


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

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

  • 降低资源消耗

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

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

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

一、内部类解析

  • 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;
        }
    
        /*
         * 获取独占锁,其内部会调用 tryAcquire(int unused) 方法来获取独占锁,
         * 如果获取失败,则会将当前线程和给定模式包裹成一个 Node 节点,将其加入到 CLH 队列尾部
         */
        public void lock()        { acquire(1); }
        // 尝试获取独占锁
        public boolean tryLock()  { return tryAcquire(1); }
        /*
         * 释放独占锁,其内部会调用 tryRelease(int unused) 方法来释放独占锁
         * 如果释放成功,且当前节点存在后继节点,则对其进行唤醒
         */
        public void unlock()      { release(1); }
        // 判断线程是否获得了独占锁 0=未获得 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 来实现独占锁的功能

  • CallerRunsPolicy

    public static class CallerRunsPolicy implements RejectedExecutionHandler {
    
        public CallerRunsPolicy() { }
    
        public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
            if (!e.isShutdown()) {
                r.run();
            }
        }
    }
    
    • 线程拒绝策略之一,将任务分配给调用线程来执行
  • AbortPolicy

    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());
        }
    }
    
    • 线程拒绝策略之一 (默认策略),直接丢弃任务,抛出异常
  • DiscardPolicy

    public static class DiscardPolicy implements RejectedExecutionHandler {
    
        public DiscardPolicy() { }
    
        public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
        }
    }
    
    • 线程拒绝策略之一,直接丢弃任务,不抛出异常
  • DiscardOldestPolicy

    public static class DiscardOldestPolicy implements RejectedExecutionHandler {
    
        public DiscardOldestPolicy() { }
    
        public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
            if (!e.isShutdown()) {
                e.getQueue().poll();
                e.execute(r);
            }
        }
    }
    
    • 线程拒绝策略之一,丢弃队列中最早的任务,不抛出异常

二、构造方法解析

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 的时间单位,类型为 TimeUnit

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

        常量名含义
        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丢弃队列中最早的任务,不抛出异常

三、线程池状态解析

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 的值)

  • 线程池有五大状态,分别是:RUNNINGSHUTDOWNSTOPTIDYINGTERMINATED

    状态作用
    RUNNING (-1)接受新任务并处理排队任务
    SHUTDOWN (0)不接受新任务,但会处理排队任务
    当线程处于 RUNNING 状态时,调用 shutdown() 方法会使线程池进入该状态
    STOP (1)不接受新任务,也不处理排队任务,同时会中断正在处理的任务
    TIDYING (2)所有任务都已终止,有效线程数 (workerCount) 为零
    当线程池进入该状态时,会调用 terminated() 方法
    TERMINATED (3)terminated() 方法执行后,线程池会进入该状态

四、方法解析

  • addWorker(Runnable firstTask, boolean core)

    private boolean addWorker(Runnable firstTask, boolean core) {
        retry:
        for (;;) {
            int c = ctl.get();
            // 获取线程池运行状态
            int rs = runStateOf(c);
    
            /*
             * 此条件可等价地转换为 rs >= SHUTDOWN && (rs != SHUTDOWN || firstTask != null || workQueue.isEmpty())
             * 即可分为以下 3 个条件,只要有一个条件满足,则表示不再添加新的线程来执行任务
             *      1、rs >= SHUTDOWN && rs != SHUTDOWN
             *          线程池状态是 STOP (1)、TIDYING (2)、TERMINATED (3) 的其中一种
             *      2、rs >= SHUTDOWN && firstTask != null
             *          线程池状态不是 RUNNING (-1) 且已经接受了新的任务
             *      3、rs >= SHUTDOWN && workQueue.isEmpty()
             *          线程池状态不是 RUNNING (-1) 且工作队列为空
             */
            if (rs >= SHUTDOWN &&
                ! (rs == SHUTDOWN &&
                   firstTask == null &&
                   ! workQueue.isEmpty()))
                return false;
    
            for (;;) {
                // 获取工作线程数
                int wc = workerCountOf(c);
                /*
                 * 如果 wc >= CAPACITY 或 wc >= corePoolSize / maximumPoolSize,则返回 false
                 * 这里第二个条件中的 core 为 addWorker() 方法的第二个参数
                 *      1、为 true 时,表示根据 corePoolSize 来进行判断
                 *      2、为 false 时,表示根据 maximumPoolSize 来进行判断
                 */
                if (wc >= CAPACITY ||
                    wc >= (core ? corePoolSize : maximumPoolSize))
                    return false;
                /*
                 * 尝试增加线程池中线程数目,
                 * 如果成功,则跳出外层循环 retry
                 */
                if (compareAndIncrementWorkerCount(c))
                    break retry;
                // 如果增加线程失败,则重新获取 ctl
                c = ctl.get();
                /*
                 * 重新获取线程池运行状态,并与先前获取的线程池运行状态进行比较,
                 * 如果两者不相等,说明线程池状态已被改变,则返回外层循环继续执行
                 */
                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 或 (如果 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();
                        /*
                         * 如果 s > largestPoolSize,
                         * 则将 s 赋值给 largestPoolSize
                         *      1、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 时,表示在新增线程时,
      会判断当前工作线程数 (workerCount) 是否小于核心线程数 (corePoolSize);
      为 false 时,表示在新增线程时,
      会判断当前工作线程数 (workerCount) 是否小于最大线程数 (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();
                 /*
                  * 此条件可等价地转换为以下 2 个条件,
                  * 只要有一个条件满足,则设置当前线程为中断状态
                  *     1、runStateAtLeast(ctl.get(), STOP) && !wt.isInterrupted()
                  *         线程池处于 STOP (1) 或 TIDYING (2) 
                  *         或 TERMINATED (3) 状态且当前线程未被中断,则设置当前线程为中断状态
                  *     2、(Thread.interrupted() && runStateAtLeast(ctl.get(), STOP)) && !wt.isInterrupted()
                  *         如果在执行 if 语句期间,执行了 shutdownNow() / shutdownNow() 方法,
                  *         则会将线程池中所有线程设为中断状态,此时调用 Thread.interrupted() 会清除当前线程的中断标识
                  *         且此时线程池处于 STOP (1) 或 TIDYING (2) 或 TERMINATED (3) 状态
                  *         且当前线程未被中断 (已被 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);
    
            /*
             * 此条件可等价地转换为以下 2 个条件,
             * 只要有一个条件满足,则将线程池中线程数目 - 1,并返回 null
             *      1、rs >= SHUTDOWN && rs >= STOP
             *          线程池状态是 STOP (1)、TIDYING (2)、TERMINATED (3) 的其中一种
             *      2、rs >= SHUTDOWN && workQueue.isEmpty()
             *          线程池状态不是 RUNNING (-1) 且工作队列为空
             */
            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)为空,则满足条件
             */
             
             
             /*
              * 此条件可等价地转换为以下 4 个条件,
              * 只要有一个条件满足,则将线程池中线程数目 - 1,
              * 并返回 null,如果失败,则返回重试
              *     1、wc > maximumPoolSize && wc > 1
              *         线程池中线程数目大于最大线程数且大于 1
              *     2、wc > maximumPoolSize && workQueue.isEmpty()
              *         线程池中线程数目大于最大线程数且工作队列为空
              *     3、(timed && timedOut) && wc > 1
              *         即当前操作需要进行超时控制且上次从
              *         工作队列中获取任务超时且线程池中线程数目大于 1
              *     4、(timed && timedOut) && workQueue.isEmpty()
              *         即当前操作需要进行超时控制且上次从
              *         工作队列中获取任务超时且工作队列为空
              */
            if ((wc > maximumPoolSize || (timed && timedOut))
                && (wc > 1 || workQueue.isEmpty())) {
                if (compareAndDecrementWorkerCount(c))
                    return null;
                continue;
            }
    
            try {
                /*
                 * 如果 timed 为 true,则表示需要对 workQueue 的 poll() 方法
                 * 进行超时控制,如果在 keepAliveTime 时间内没有获取到任务,则返回 null;
                 * 如果 timed 为 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();
    
        // 获取 ctl
        int c = ctl.get();
        /*
         * 如果线程池中线程数目小于 corePoolSize,
         * 则在线程池中创建一个新的线程来执行任务
         */
        if (workerCountOf(c) < corePoolSize) {
            if (addWorker(command, true))
                return;
            // 重新获取 ctl
            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)
                // 如果为 0,则在线程池中创建一个新的线程
                addWorker(null, false);
        }
        /*
         * 在线程池中创建一个新的线程来执行任务
         * 如果创建失败,则使用线程拒绝策略对任务进行处理
         */
        else if (!addWorker(command, false))
            reject(command);
    }
    
    • execute() 方法主要用于提交任务,交由工作线程来进行处理

    • 任务执行流程

      在这里插入图片描述

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

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

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

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


五、参考资料

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值