Java-API简析_java.util.concurrent.ThreadPoolExecutor类(基于 Latest JDK)(浅析源码)

【版权声明】未经博主同意,谢绝转载!(请尊重原创,博主保留追究权)
https://blog.csdn.net/m0_69908381/article/details/135382255
出自【进步*于辰的博客

启发博文:《Java 多线程:彻底搞懂线程池》(转发)。
大家可以先阅读这篇文章,提前对线程池有一定了解,这样更容易理解此类源码。

注:依赖类:ExecutorsTimeUnit

文章目录

1、概述

继承关系:

  • java.lang.Object
    • java.util.concurrent.AbstractExecutorService
      • java.util.concurrent.ThreadPoolExecutor

实现的所有接口
ExecutorExecutorService
已知直接子类:
ScheduledThreadPoolExecutor


public class ThreadPoolExecutor extends AbstractExecutorService

ExecutorService ,使用一个可能几个池线程执行每个提交的任务,通常使用Executors工厂方法进行配置。

线程池解决了两个不同的问题:它们通常在执行大量异步任务时提供改进的性能,这是由于减少了每个任务的调用开销,并且它们提供了一种绑定和管理资源的方法,包括执行集合时所消耗的线程。每个 ThreadPoolExecutor 还维护一些基本统计信息,如完成任务数。

为了在各种上下文中有用,该类提供了许多可调参数和可扩展性钩子。 但是,程序员被要求使用更方便的Executors工厂方法Executors.newCachedThreadPool() (无界线程池,具有自动线程回收)、Executors.newFixedThreadPool(int) (固定大小线程池)和Executors.newSingleThreadExecutor() (单个后台线程),为最常见的使用场景预配置设置。 否则,在手动配置和调整此类时,请使用以下指南:

核心和最大池大小
ThreadPoolExecutor 将根据 corePoolSize(核心,参见 getCorePoolSize())和 maximumPoolSize(最大池大小,参见 getMaximumPoolSize())设置的边界自动调整池大小。当新任务在方法 execute(java.lang.Runnable) 中提交时,如果运行的线程少于 corePoolSize,则创建新线程来处理请求,即使其他辅助线程是空闲的。如果运行的线程多于 corePoolSize 而少于 maximumPoolSize,则仅当队列满时才创建新线程。如果设置的 corePoolSizemaximumPoolSize 相同,则创建了固定大小的线程池。如果将 maximumPoolSize 设置为基本的无界值(如 Integer.MAX_VALUE),则允许池适应任意数量的并发任务。在大多数情况下,corePoolSizemaximumPoolSize仅基于构造来设置,不过也可以使用 setCorePoolSize(int)setMaximumPoolSize(int) 进行动态更改。

按需构造
默认情况下,即使核心线程最初只是在新任务需要时才创建和启动的,也可以使用方法 prestartCoreThread()prestartAllCoreThreads() 对其进行动态重写。

创建新线程
使用 ThreadFactory 创建新线程。如果没有另外说明,则在同一个 ThreadGroup 中一律使用 Executors.defaultThreadFactory() 创建线程,并且这些线程具有相同的 NORM_PRIORITY 优先级和非守护进程状态。通过提供不同的 ThreadFactory,可以改变线程的名称、线程组、优先级、守护进程状态等等。如果 ThreadFactory 未能创建一个线程,当访问 newThreadnull时,程序将继续运行,但可能无法执行任何任务。
使用池的工作线程或其他线程应具备“modifythread”权限(RuntimePermission 权限)。如果不具有此权限,服务可能会被降级,配置更改可能不会及时生效,并且关闭池可能处于终止状态,即未完成。

保持活动时间
如果池中当前有多于 corePoolSize 的线程,则这些多出的线程在空闲时间超过 keepAliveTime 时将会终止(参见 getKeepAliveTime(java.util.concurrent.TimeUnit))。这提供了当池处于非活动状态时减少资源消耗的方法。如果池后来变得更为活动,则可以创建新的线程。也可以使用方法 setKeepAliveTime(long, java.util.concurrent.TimeUnit) 动态地更改此参数。使用 Long.MAX_VALUETimeUnit.NANOSECONDS 的值在关闭前有效地从以前的终止状态禁用空闲线程。

排队
所有 BlockingQueue 都可用于传输和保持提交的任务。可以使用此队列与池大小进行交互:

  • 如果运行的线程少于 corePoolSize,则 Executor 始终首选添加新的线程,而不进行排队。
  • 如果运行的线程等于或多于 corePoolSize,则 Executor 始终首选将请求加入队列,而不添加新的线程。
  • 如果无法将请求加入队列,则创建新的线程,除非创建此线程超出 maximumPoolSize,在这种情况下,任务将被拒绝。
排队有三种通用策略:
  1. 直接提交。工作队列的默认选项是 SynchronousQueue,它将任务直接提交给线程而不保持它们。在此,如果不存在可用于立即运行任务的线程,则试图把任务加入队列将失败,因此会构造一个新的线程。此策略可以避免在处理可能具有内部依赖性的请求集合时出现锁定。直接提交通常要求无界 maximumPoolSizes 以避免拒绝新提交的任务。当命令以超过队列所能处理的平均数连续到达时,此策略允许无界线程具有增长的可能性。
  1. 无界队列。使用无界队列(例如,不具有预定义容量的 LinkedBlockingQueue)将导致在所有 corePoolSize 线程都忙的情况下将新任务加入队列。这样,创建的线程就不会超过 corePoolSize(因此,maximumPoolSize 的值也就无效了)。当每个任务完全独立于其他任务,即任务执行互不影响时,适合于使用无界队列;例如,在 Web 页服务器中。这种排队可用于处理瞬态突发请求,当命令以超过队列所能处理的平均数连续到达时,此策略允许无界线程具有增长的可能性。
  1. 有界队列。当使用有限的 maximumPoolSizes 时,有界队列(如 ArrayBlockingQueue)有助于防止资源耗尽,但是可能较难调整和控制。队列大小和最大池大小可能需要相互折中:使用大型队列和小型池可以最大限度地降低 CPU 使用率、操作系统资源和上下文切换开销,但是可能导致人工降低吞吐量。如果任务频繁阻塞(例如,如果它们是 I/O 边界),则系统可能为超过您许可的更多线程安排时间。使用小型队列通常要求较大的池大小,CPU 使用率较高,但是可能遇到不可接受的调度开销,这样也会降低吞吐量。

被拒绝的任务
当 Executor 已经关闭,并且 Executor 将有限边界用于最大线程和工作队列容量,且已经饱和时,在方法 execute(java.lang.Runnable) 中提交的新任务将被拒绝。在以上两种情况下,execute()都将调用其 RejectedExecutionHandlerRejectedExecutionHandler.rejectedExecution(java.lang.Runnable, java.util.concurrent.ThreadPoolExecutor) 方法。下面提供了四种预定义的处理程序策略:

  1. 在默认的 ThreadPoolExecutor.AbortPolicy 中,处理程序遭到拒绝将抛出运行时 RejectedExecutionException
  2. ThreadPoolExecutor.CallerRunsPolicy 中,线程调用运行该任务的 execute 本身。此策略提供简单的反馈控制机制,能够减缓新任务的提交速度。
  3. ThreadPoolExecutor.DiscardPolicy 中,不能执行的任务将被删除。
  4. ThreadPoolExecutor.DiscardOldestPolicy 中,如果执行程序尚未关闭,则位于工作队列头部的任务将被删除,然后重试执行程序(如果再次失败,则重复此过程)。

定义和使用其他种类的 RejectedExecutionHandler 类也是可能的,但这样做需要非常小心,尤其是当策略仅用于特定容量或排队策略时。

挂钩方法
此类提供 protected 可重写的 beforeExecute(java.lang.Thread, java.lang.Runnable)afterExecute(java.lang.Runnable, java.lang.Throwable) 方法,这两种方法分别在执行每个任务之前和之后调用。它们可用于操纵执行环境。例如,重新初始化 ThreadLocal、搜集统计信息或添加日志条目。此外,还可以重写方法 terminated() 来执行 Executor 完全终止后需要完成的所有特殊处理。

如果挂钩或回调方法抛出异常,则内部辅助线程将依次失败并突然终止。

队列维护
方法 getQueue() 允许出于监控和调试目的而访问工作队列。强烈反对出于其他任何目的而使用此方法。remove(java.lang.Runnable)purge() 这两种方法可用于在取消大量已排队任务时帮助进行存储回收。

扩展示例。此类的大多数扩展可以重写一个或多个受保护的挂钩方法。例如,下面是一个添加了简单的暂停/恢复功能的子类:

classclass PausableThreadPoolExecutor extends ThreadPoolExecutor {
    private boolean isPaused;
    private ReentrantLock pauseLock = new ReentrantLock();
    private Condition unpaused = pauseLock.newCondition();

    public PausableThreadPoolExecutor(...) {
        super(...);
    }

    protected void beforeExecute(Thread t, Runnable r) {
        super.beforeExecute(t, r);
        pauseLock.lock();
        try {
            while (isPaused) unpaused.await();
        } catch (InterruptedException ie) {
            t.interrupt();
        } finally {
            pauseLock.unlock();
        }
    }

    public void pause() {
        pauseLock.lock();
        try {
            isPaused = true;
        } finally {
            pauseLock.unlock();
        }
    }

    public void resume() {
        pauseLock.lock();
        try {
            isPaused = false;
            unpaused.signalAll();
        } finally {
            pauseLock.unlock();
        }
    }
}

从以下版本开始:
1.5

1.1 说明

此类是线程池,核心方法是execute()(第3.2项)、addWorker()(第4.4项),我暂未整理线程池相关理论,大家可以查阅启发博文。在此仅引用一张图线程池的业务流程图:
在这里插入图片描述
大家在阅读本篇解析时结合这张图会更容易理解。

2、嵌套类摘要

2.1 拒绝策略

  1. static class ThreadPoolExecutor.AbortPolicy:用于被拒绝任务的处理程序,它将抛出 RejectedExecutionException。
  2. static class ThreadPoolExecutor.CallerRunsPolicy
    用于被拒绝任务的处理程序,它直接在 execute 方法的调用线程中运行被拒绝的任务;如果执行程序已关闭,则会丢弃该任务。
  3. static class ThreadPoolExecutor.DiscardOldestPolicy
    用于被拒绝任务的处理程序,它放弃最旧的未处理请求,然后重试 execute;如果执行程序已关闭,则会丢弃该任务。
  4. static class ThreadPoolExecutor.DiscardPolicy
    用于被拒绝任务的处理程序,默认情况下它将放弃被拒绝的任务。

2.2 private final class Worker

2.2.1 预览

工作者。

private final class Worker extends AbstractQueuedSynchronizer implements Runnable {
    final Thread thread;// 执行任务的线程,如果工厂创建失败则为 null
    Runnable firstTask;// 第一个任务,可能为 null
    volatile long completedTasks;// 完成任务数

    Worker(Runnable firstTask) {
        setState(-1); // inhibit interrupts until runWorker
        this.firstTask = firstTask;
        this.thread = getThreadFactory().newThread(this);
    }
    ...
}

后续补充解析。

3、构造方法摘要

3.1 int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue

用给定的初始参数和默认的线程工厂及处理程序创建新的 ThreadPoolExecutor。

public ThreadPoolExecutor(int corePoolSize,
                          int maximumPoolSize,
                          long keepAliveTime,
                          TimeUnit unit,
                          BlockingQueue<Runnable> workQueue) {
    this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
         Executors.defaultThreadFactory(), defaultHandler);// 默认线程工厂、默认拒绝策略
}

关于defaultThreadFactory(),见 Executors 类的第2.5项;关于defaultHandler,见第6项。

3.2 int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, RejectedExecutionHandler handler

用给定的初始参数创建新的 ThreadPoolExecutor。

3.3 int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, ThreadFactory threadFactory

用给定的初始参数创建新的 ThreadPoolExecutor。

前3个构造方法都仅调用下1项。

3.4 int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, ThreadFactory threadFactory, RejectedExecutionHandler handler

用给定的初始参数创建新的 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);// 将 keepAliveTime 换算成“纳秒”
    this.threadFactory = threadFactory;
    this.handler = handler;
}

关于toNanos(),见 TimeUnit 类的4.7项。

构造方法中无复杂逻辑,都是属性初始化,见第5项。

3、方法摘要

3.1 boolean awaitTermination(long timeout, TimeUnit unit)

请求关闭、发生超时或者当前线程中断,无论哪一个首先发生之后,都将导致阻塞,直到所有任务完成执行。

3.2 void execute(Runnable command)

在将来某个时间执行给定任务。

public void execute(Runnable command) {
    if (command == null)
        throw new NullPointerException();

    int c = ctl.get();
    if (workerCountOf(c) < corePoolSize) {// 若工作线程数小于核心工作线程数,则添加任务并执行
        if (addWorker(command, true))
            return;
        c = ctl.get();
    }
    if (isRunning(c) && workQueue.offer(command)) {// 若线程池处于运行状态,且任务队列可添加任务
        int recheck = ctl.get();
        // 再次校验线程池状态,若线程池不处于运行状态,则拒绝任务,并将任务从任务队列中移除
        if (! isRunning(recheck) && remove(command))
            reject(command);
        else if (workerCountOf(recheck) == 0)// ------A
            addWorker(null, false);
    }
    // 线程池不处于运行状态,直接拒绝任务(推演addWorker的结果,第一个if)
    else if (!addWorker(command, false))
        reject(command);
}

引用【最后】中那篇博文的一张业务流程图:
在这里插入图片描述
源码中 A 说明:
如图所示,这种情况下会添加非核心工作线程处理任务,但我推演了一遍addworker(),发现仅进行了如下操作:

  1. ctl + 1
  2. 调用addWorkerFailed()

并没有其他操作,故我暂且不理解 A 的意图,可能是因为对线程池的理解不够。

后续补充解析。

3.3 int getActiveCount()

返回主动执行任务的近似线程数。

3.4 long getCompletedTaskCount()

返回已完成执行的近似任务总数。

3.5 int getCorePoolSize()

返回核心线程数。

3.6 long getKeepAliveTime(TimeUnit unit)

返回线程保持活动的时间,该时间就是超过核心池大小的线程可以在终止前保持空闲的时间值。

3.7 int getLargestPoolSize()

返回曾经同时位于池中的最大线程数。

3.8 int getMaximumPoolSize()

返回允许的最大线程数。

3.9 int getPoolSize()

返回池中的当前线程数。

3.10 BlockingQueue<Runnable> getQueue()

返回此执行程序使用的任务队列。

3.11 RejectedExecutionHandler getRejectedExecutionHandler()

返回用于未执行任务的当前处理程序。

3.12 long getTaskCount()

返回计划执行的近似任务总数。

3.13 ThreadFactory getThreadFactory()

返回用于创建新线程的线程工厂。

3.14 boolean isShutdown()

如果此执行程序已关闭,则返回 true。

3.15 boolean isTerminated()

如果关闭后所有任务都已完成,则返回 true。

3.16 boolean isTerminating()

如果此执行程序处于在 shutdown 或 shutdownNow 之后正在终止但尚未完全终止的过程中,则返回 true。

3.17 int prestartAllCoreThreads()

启动所有核心线程,使其处于等待工作的空闲状态。

3.18 boolean prestartCoreThread()

启动核心线程,使其处于等待工作的空闲状态。

3.19 void purge()

试图从工作队列移除所有已取消的 Future 任务。

3.20 boolean remove(Runnable task)

从执行程序的内部队列中移除此任务(如果出现),这样如果尚未开始,则其不再运行。

3.21 void setCorePoolSize(int corePoolSize)

设置核心线程数。

3.22 void setKeepAliveTime(long time, TimeUnit unit)

设置线程在终止前可以保持空闲的时间限制。

3.23 void setMaximumPoolSize(int maximumPoolSize)

设置允许的最大线程数。

3.24 void setRejectedExecutionHandler(RejectedExecutionHandler handler)

设置用于未执行任务的新处理程序。

3.25 void setThreadFactory(ThreadFactory threadFactory)

设置用于创建新线程的线程工厂。

3.26 void shutdown()

按过去执行已提交任务的顺序发起一个有序的关闭,但是不接受新任务。

3.27 List<Runnable> shutdownNow()

尝试停止所有的活动执行任务、暂停等待任务的处理,并返回等待执行的任务列表。

3.28 protected void terminated()

当 Executor 已经终止时调用的方法。

4、方法摘要(不开放)

4.1 protected void afterExecute(Runnable r, Throwable t)

基于完成执行给定 Runnable 所调用的方法。

4.2 protected void beforeExecute(Thread t, Runnable r)

在执行给定线程中的给定 Runnable 之前调用的方法。

4.3 protected void finalize()

当不再引用此执行程序时,调用 shutdown()

4.4 private boolean addWorker(Runnable firstTask, boolean core)

添加工作线程并且启动工作线程。

private boolean addWorker(Runnable firstTask, boolean core) {
    retry:
    for (;;) {
        int c = ctl.get();// 获取ctl的值,初始值:-2^29
        int rs = runStateOf(c);// 获取线程池状态,初始值:-2^29(RUNNING)

		// 校验线程池状态,判断是否可添加任务
        if (rs >= SHUTDOWN &&// 从第6.2项可看出,大于SHUTDOWN的四个状态都不能再添加任务
            ! (rs == SHUTDOWN &&
               firstTask == null &&
               ! workQueue.isEmpty()))// 工作队列不为空
               // 如果这三个条件都满足,说明是要添加非核心工作线程去处理任务队列中任务
               // 若这3个条件有一个不满足,也无法添加任务,暂不知为何
            return false;

		// 校验工作线程数
        for (;;) {
            int wc = workerCountOf(c);// 返回工作线程数
            if (wc >= CAPACITY ||// 工作线程数不小于容量
                wc >= (core ? corePoolSize : maximumPoolSize))
                return false;
            if (compareAndIncrementWorkerCount(c))// ctl + 1。见下1项
                break retry;
            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 {
        w = new Worker(firstTask);// 构造工作线程
        final Thread t = w.thread;
        if (t != null) {
            final ReentrantLock mainLock = this.mainLock;
            mainLock.lock();// 上锁,令其他线程休眠
            try {
                // 获取锁后重新检查线程池状态
                // 若线程工厂失败或上锁前线程池已停止,则返回
                int rs = runStateOf(ctl.get());

                if (rs < SHUTDOWN ||// 线程池状态为 RUNNING
                	// SHUTDOWN状态不再接收新任务
                    (rs == SHUTDOWN && firstTask == null)) {// 暂不明白适用于后者的情形
                    if (t.isAlive()) // 检查线程是否是可启动的,即是否处于活动状态
                        throw new IllegalThreadStateException();
                    workers.add(w);
                    int s = workers.size();
                    if (s > largestPoolSize)// 见第5.2项
                        largestPoolSize = s;
                    workerAdded = true;
                }
            } finally {
                mainLock.unlock();// 解锁
            }
            if (workerAdded) {
                t.start();
                workerStarted = true;
            }
        }
    } finally {
        if (! workerStarted)
            addWorkerFailed(w);// 见第4.8项
    }
    return workerStarted;
}

关于runStateOf()/workerCountOf(),见第6.4项;关于lock(),见第6.3项。

P S : PS: PS目前我对此方法的业务流程理解地还不够透彻,后续补充业务流程图。

4.5 private boolean compareAndIncrementWorkerCount(int expect)

尝试通过 CAS 序列修改ctlworkerCount字段。(增加1

private boolean compareAndIncrementWorkerCount(int expect) {
    return ctl.compareAndSet(expect, expect + 1);// 原子化地将值设置为指定的更新值
}

4.6 private void decrementWorkerCount()

减少工作线程数量。

private void decrementWorkerCount() {
    do {} while (! compareAndDecrementWorkerCount(ctl.get()));
}

后续解析。

4.6 final void tryTerminate()

尝试终止当前线程池。

final void tryTerminate() {
    for (;;) {
        int c = ctl.get();
        if (isRunning(c) ||
            runStateAtLeast(c, TIDYING) ||
            (runStateOf(c) == SHUTDOWN && ! workQueue.isEmpty()))
            return;
        if (workerCountOf(c) != 0) { // Eligible to terminate
            interruptIdleWorkers(ONLY_ONE);
            return;
        }

        final ReentrantLock mainLock = this.mainLock;
        mainLock.lock();
        try {
            if (ctl.compareAndSet(c, ctlOf(TIDYING, 0))) {
                try {
                    terminated();
                } finally {
                    ctl.set(ctlOf(TERMINATED, 0));
                    termination.signalAll();
                }
                return;
            }
        } finally {
            mainLock.unlock();
        }
        // else retry on failed CAS
    }
}

后续解析。

4.8 private void addWorkerFailed(Worker w)

从工作线程集合中移除指定工作线程,同时减少工作线程数并尝试终止当前线程池。

private void addWorkerFailed(Worker w) {
    final ReentrantLock mainLock = this.mainLock;
    mainLock.lock();
    try {
        if (w != null)
            workers.remove(w);
        decrementWorkerCount();
        tryTerminate();
    } finally {
        mainLock.unlock();
    }
}

关于decrementWorkerCount(),见第6项;关于tryTerminate(),见上1项。

4.9 private static boolean isRunning(int c)

判断线程池是否处于运行状态。

private static boolean isRunning(int c) {
    return c < SHUTDOWN;
}

5、属性摘要

5.1 核心属性

// 核心工作线程数
private volatile int corePoolSize;// 当前任务执行结束后,不会销毁
// 线程池可创建的最大工作线程数
private volatile int maximumPoolSize;
// 非核心工作线程在任务队列中的等待时间
private volatile long keepAliveTime;
;// 任务队列(阻塞)
private final BlockingQueue<Runnable> workQueue
// 线程工厂
private volatile ThreadFactory threadFactory;
// 线程池中线程数大于最大工作线程数时的拒绝策略
private volatile RejectedExecutionHandler handler;
// 工作线程集合
private final HashSet<Worker> workers = new HashSet<Worker>();

5.2 其他属性

// 已达到的最大池大小(线程数)。仅在mainLock条件下访问
private int largestPoolSize;

private long completedTaskCount;// 完成任务数
private volatile boolean allowCoreThreadTimeOut;// 是否允许核心线程超时

6、字段摘要

6.1 基础字段

// 与 Integer 是“兄弟”,底层也是 int value
private final AtomicInteger ctl = new AtomicInteger(ctlOf(RUNNING, 0));// 线程池控制状态。value = RUNNING
private static final int COUNT_BITS = Integer.SIZE - 3;// 29
// 0001...1111 → 2^29 - 1 = 536870911
private static final int CAPACITY   = (1 << COUNT_BITS) - 1;// 容量,能记录的工作线程的最大个数

ctl“封装”了两个概念 / 变量:(并未“真实”定义,只是“概念”,相应值的计算方法见【相应方法】)

  1. workerCount:有效工作线程数,包括已允许启动的(工作线程)和不允许启动而停止的(工作线程),其值可能会短暂地与实际存活线程数不同,
    例如:在任务待处理时线程工厂创建线程失败,或者在线程终止前退出线程时线程仍在执行,会为workerCount设置一个“快照”,用户可见的工作线程数是workers中的线程个数的一个“报告”。(PS:这段阐述出自注释,暂不理解)
  2. runState:运行状态。

为何CAPACITY的值为 229 - 1?注释中表示,是为了将其打包成一个int,暂不理解。

6.2 生命周期状态

// 运行状态
private static final int RUNNING    = -1 << COUNT_BITS;// 1110...0000 = -2^29 → 111
// 关闭状态
private static final int SHUTDOWN   =  0 << COUNT_BITS;// 0000...0000 → 000
// 停止状态
private static final int STOP       =  1 << COUNT_BITS;// 0010...0000 = 2^29 → 001
// 过渡状态
private static final int TIDYING    =  2 << COUNT_BITS;// 0100...000 = 2^30 → 010
// 终止状态
private static final int TERMINATED =  3 << COUNT_BITS;// 0110...0000 = 2^30 + 2^29 → 011

大家先看张图。
在这里插入图片描述
说明:

  1. A:运行状态。接收新任务,也处理任务队列中的任务。
  2. B:关闭状态。正在处理的任务正常进行,不接收新任务,但仍会处理任务队列中的任务。
  3. C:停止状态。不接收新任务,不再处理任务队列中的任务,正在处理的任务会被中断。
  4. D:过渡状态,所有任务都已完成,workerCount 为 0,代表线程池马上关闭,将要执行 terminated()
  5. E:终止状态。

6.3 其他字段

// 锁定工人设置和相关记账的访问权限
private final ReentrantLock mainLock = new ReentrantLock();

private final Condition termination = mainLock.newCondition();

private static final RejectedExecutionHandler defaultHandler =
        new AbortPolicy();
        
private static final RuntimePermission shutdownPerm =
        new RuntimePermission("modifyThread");

private final AccessControlContext acc;// 上下文

字段旗下方法说明:

  1. mainLock.lock():如果锁未被另一个线程持有,则获取锁并立即返回,将锁定保持数设置为1;如果当前线程已经持有锁,则持有数增加1,方法立即返回;如果锁由另一个线程持有,则当前线程被禁用以进行线程调度,让其进入休眠状态,直到获取了锁为止,
    此时锁定保持数被设置为1

6.4 相应方法

// 返回指定线程池状态
private static int runStateOf(int c)     { return c & ~CAPACITY; }
// 返回有效工作线程数
private static int workerCountOf(int c)  { return c & CAPACITY; }
// 返回ctl的值
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;
}

最后

如果大家对本篇解析仍有所疑惑,推荐一篇博文《万字解析!Java - ThreadPoolExecutor源码》(转发)。

如果大家需要Java-API文档,我上传了《Java-API文档-包含5/8/11三个版本》。


本文暂缓更新。

  • 22
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

进步·于辰

谢谢打赏!!很高兴可以帮到你!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值