看图学源码之 线程池源码分析

线程池

ThreadPoolExecutor

池化技术:便于管理和回收线程,可以进行重复利用,减少创建和回收线程的开销

源码

image-20231203182010066

image-20231203182035495

Executor
public interface Executor {
    /**
     * 在将来的某个时间执行给定的命令。该命令可以在  新线程、线程池 或 调用线程中执行,具体取决于Executor实现
     */
    void execute(Runnable command);  //定义提交的任务
}
ExecutorService
public interface ExecutorService extends Executor {

    /**
     * 启动有序关闭,继续执行先前提交的任务,但不会接受新任务。如果已经关闭,调用不会产生额外的效果。
		 * 该方法不等待之前提交的任务完成执行。使用awaitTermination来做到这一点
     */
    void shutdown();

    /**
     * 尝试停止所有正在执行的任务,停止正在等待的任务的处理,并返回正在等待执行的任务的列表。
     * 此方法不等待主动执行的任务终止。使用awaitTermination来做到这一点。
     * 除了尽最大努力尝试停止处理主动执行的任务之外,没有任何保证。
     * 例如,典型的实现将通过Thread.interrupt取消,因此任何无法响应中断的任务可能永远不会终止。
     */
    List<Runnable> shutdownNow();

    /**
     * 如果此执行器已关闭,则返回true 
     */
    boolean isShutdown();

    /**
     * 如果关闭后所有任务均已完成,则返回true 。请注意,除非首先调用shutdown或shutdownNow否则isTerminated永远不会为true 。
     */
    boolean isTerminated();

    /**
     * 阻塞,直到所有任务在关闭请求后完成执行,或者发生超时,或者当前线程被中断,以先发生者为准。
     */
    boolean awaitTermination(long timeout, TimeUnit unit) throws InterruptedException;

    /**
     * 提交一个返回值的任务来执行,并返回一个表示任务待处理结果的 Future。 
     * Future 的get方法将在成功完成后返回任务的结果。
     * 如果您想立即阻止等待任务,可以使用result = exec.submit(aCallable).get();
     */
    <T> Future<T> submit(Callable<T> task);

    /**
     * 提交一个 Runnable 任务来执行并返回一个表示该任务的 Future。 Future 的get方法将在成功完成后返回  给定的结果。
     */
    <T> Future<T> submit(Runnable task, T result);

    /**
     * 提交一个 Runnable 任务来执行并返回一个表示该任务的 Future。 Future 的get方法在成功完成后将返回  null 。
     */
    Future<?> submit(Runnable task);

    /**
     * 执行给定的任务,在全部完成时返回保存其状态和结果的 Future 列表。对于返回列表中的每个元素, Future.isDone都为true 。
     * 请注意,已完成的任务可能会正常终止或通过引发异常终止。如果在此操作进行期间修改给定集合,则此方法的结果是未定义的。
     */
    <T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks)throws InterruptedException;

    /**
     * 执行给定的任务,当所有任务完成或超时到期(以先发生者为准)时,返回保存其状态和结果的 Future 列表。
     * 对于返回列表中的每个元素, Future.isDone都为true 。返回后,未完成的任务将被取消。
     * 请注意,已完成的任务可能会正常终止或通过引发异常终止。如果在此操作进行期间修改给定集合,则此方法的结果是未定义的。
     */
    <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
package java.util.concurrent;
import java.util.*;

/**
 * 提供ExecutorService执行方法的默认实现。
 * 该类使用newTaskFor返回的RunnableFuture实现了submit 、 invokeAny和invokeAll方法,默认为该包中提供的FutureTask类。
 * 例如submit(Runnable)的实现创建一个执行并返回的关联RunnableFuture 。子类可以重写newTaskFor方法以返回除FutureTask之外的RunnableFuture实现。
 */
public abstract class AbstractExecutorService implements ExecutorService {

    /**
     * 返回给定可运行对象和默认值的RunnableFuture 
     */
    protected <T> RunnableFuture<T> newTaskFor(Runnable runnable, T value) {
        return new FutureTask<T>(runnable, value);
    }

    /**
     * 返回给定可调用任务的RunnableFuture 。
     */
    protected <T> RunnableFuture<T> newTaskFor(Callable<T> callable) {
        return new FutureTask<T>(callable);
    }
  
  
【任务在线程池中的执行入口: submit()   execute()/**
     * RejectedExecutionException – 如果无法安排任务执行     NullPointerException – 如果任务为 null
     */
    public Future<?> submit(Runnable task) {
        if (task == null) throw new NullPointerException();
     	 	//封装任务
        RunnableFuture<Void> ftask = newTaskFor(task, null);
      	//执行任务
        execute(ftask);
      	//返回 Future
        return ftask;
    }

    /**
     * RejectedExecutionException – 如果无法安排任务执行     NullPointerException – 如果任务为 null
     */
    public <T> Future<T> submit(Runnable task, T result) {
        if (task == null) throw new NullPointerException();
       	//封装任务
        RunnableFuture<T> ftask = newTaskFor(task, result);
      //执行任务
        execute(ftask);
      //返回 Future
        return ftask;
    }

    /**
     * RejectedExecutionException – 如果无法安排任务执行     NullPointerException – 如果任务为 null
     */
    public <T> Future<T> submit(Callable<T> task) {
        if (task == null) throw new NullPointerException();
        RunnableFuture<T> ftask = newTaskFor(task);
        execute(ftask);
        return ftask;
    }

    /**
     * the main mechanics of invokeAny.
     */
    private <T> T doInvokeAny(Collection<? extends Callable<T>> tasks,
                              boolean timed, long nanos)
        throws InterruptedException, ExecutionException, TimeoutException {
        if (tasks == null)
            throw new NullPointerException();
        int ntasks = tasks.size();
        if (ntasks == 0)
            throw new IllegalArgumentException();
        ArrayList<Future<T>> futures = new ArrayList<Future<T>>(ntasks);
        ExecutorCompletionService<T> ecs = new ExecutorCompletionService<T>(this);

        // For efficiency, especially in executors with limited
        // parallelism, check to see if previously submitted tasks are
        // done before submitting more of them. This interleaving
        // plus the exception mechanics account for messiness of main
        // loop.

        try {
            // Record exceptions so that if we fail to obtain any
            // result, we can throw the last exception we got.
            ExecutionException ee = null;
            final long deadline = timed ? System.nanoTime() + nanos : 0L;
            Iterator<? extends Callable<T>> it = tasks.iterator();

            // Start one task for sure; the rest incrementally
            futures.add(ecs.submit(it.next()));
            --ntasks;
            int active = 1;

            for (;;) {
                Future<T> f = ecs.poll();
                if (f == null) {
                    if (ntasks > 0) {
                        --ntasks;
                        futures.add(ecs.submit(it.next()));
                        ++active;
                    }
                    else if (active == 0)
                        break;
                    else if (timed) {
                        f = ecs.poll(nanos, TimeUnit.NANOSECONDS);
                        if (f == null)
                            throw new TimeoutException();
                        nanos = deadline - System.nanoTime();
                    }
                    else
                        f = ecs.take();
                }
                if (f != null) {
                    --active;
                    try {
                        return f.get();
                    } catch (ExecutionException eex) {
                        ee = eex;
                    } catch (RuntimeException rex) {
                        ee = new ExecutionException(rex);
                    }
                }
            }

            if (ee == null)
                ee = new ExecutionException();
            throw ee;

        } finally {
            for (int i = 0, size = futures.size(); i < size; i++)
                futures.get(i).cancel(true);
        }
    }

    public <T> T invokeAny(Collection<? extends Callable<T>> tasks)
        throws InterruptedException, ExecutionException {
        try {
            return doInvokeAny(tasks, false, 0);
        } catch (TimeoutException cannotHappen) {
            assert false;
            return null;
        }
    }

    public <T> T invokeAny(Collection<? extends Callable<T>> tasks,
                           long timeout, TimeUnit unit)
        throws InterruptedException, ExecutionException, TimeoutException {
        return doInvokeAny(tasks, true, unit.toNanos(timeout));
    }

    public <T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks)
        throws InterruptedException {
        if (tasks == null)
            throw new NullPointerException();
        ArrayList<Future<T>> futures = new ArrayList<Future<T>>(tasks.size());
        boolean done = false;
        try {
            for (Callable<T> t : tasks) {
                RunnableFuture<T> f = newTaskFor(t);
                futures.add(f);
                execute(f);
            }
            for (int i = 0, size = futures.size(); i < size; i++) {
                Future<T> f = futures.get(i);
                if (!f.isDone()) {
                    try {
                        f.get();
                    } catch (CancellationException ignore) {
                    } catch (ExecutionException ignore) {
                    }
                }
            }
            done = true;
            return futures;
        } finally {
            if (!done)
                for (int i = 0, size = futures.size(); i < size; i++)
                    futures.get(i).cancel(true);
        }
    }

    public <T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks,
                                         long timeout, TimeUnit unit)
        throws InterruptedException {
        if (tasks == null)
            throw new NullPointerException();
        long nanos = unit.toNanos(timeout);
        ArrayList<Future<T>> futures = new ArrayList<Future<T>>(tasks.size());
        boolean done = false;
        try {
            for (Callable<T> t : tasks)
                futures.add(newTaskFor(t));

            final long deadline = System.nanoTime() + nanos;
            final int size = futures.size();

            // Interleave time checks and calls to execute in case
            // executor doesn't have any/much parallelism.
            for (int i = 0; i < size; i++) {
                execute((Runnable)futures.get(i));
                nanos = deadline - System.nanoTime();
                if (nanos <= 0L)
                    return futures;
            }

            for (int i = 0; i < size; i++) {
                Future<T> f = futures.get(i);
                if (!f.isDone()) {
                    if (nanos <= 0L)
                        return futures;
                    try {
                        f.get(nanos, TimeUnit.NANOSECONDS);
                    } catch (CancellationException ignore) {
                    } catch (ExecutionException ignore) {
                    } catch (TimeoutException toe) {
                        return futures;
                    }
                    nanos = deadline - System.nanoTime();
                }
            }
            done = true;
            return futures;
        } finally {
            if (!done)
                for (int i = 0, size = futures.size(); i < size; i++)
                    futures.get(i).cancel(true);
        }
    }

}
ThreadPoolExecutor

线程的状态

image-20231203182358891

image-20231203182115545

package java.util.concurrent;

import java.security.AccessControlContext;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.concurrent.locks.AbstractQueuedSynchronizer;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.*;

/**
 *ExecutorService使用可能的多个池线程之一执行每个提交的任务,通常使用Executors工厂方法进行配置。
线程池解决了两个不同的问题:
1、由于减少了每个任务的调用开销,它们通常在执行大量异步任务时提供改进的性能,
2、它们提供了一种限制和管理资源的方法,包括执行一组异步任务时消耗的线程。任务。每个ThreadPoolExecutor还维护一些基本统计数据,例如已完成任务的数量。

为了在广泛的上下文中发挥作用,此类提供了许多可调整的参数和可扩展性挂钩。但是,建议程序员使用更方便的Executors工厂方法Executors.newCachedThreadPool (无界线程池,具有自动线程回收功能)、 Executors.newFixedThreadPool (固定大小线程池)和Executors.newSingleThreadExecutor (单后台线程),这些方法可以预先配置设置最常见的使用场景。
否则,请在手动配置和调整此类时使用以下指南:

按需施工
	默认情况下,即使是核心线程也仅在新任务到达时才最初创建和启动,但这可以使用方法prestartCoreThread或prestartAllCoreThreads动态覆盖。如果您使用非空队列构造池,您可能需要预启动线程。


	
	
存活次数
	如果池当前拥有超过 corePoolSize 的线程,则多余的线程如果空闲时间超过 keepAliveTime,将被终止。
	这提供了一种在池未被积极使用时减少资源消耗的方法。
	如果池稍后变得更加活跃,则会构造新线程。还可以使用方法setKeepAliveTime(long, TimeUnit)动态更改此参数。
	使用Long.MAX_VALUE TimeUnit.NANOSECONDS值可以有效地禁止空闲线程在关闭之前终止。默认情况下,仅当线程数超过 corePoolSize 时才应用保持活动策略
	但是,只要 keepAliveTime 值非零,也可以使用方法allowCoreThreadTimeOut(boolean)将此超时策略应用于核心线程。

钩子方法
		此类提供protected可重写beforeExecute(Thread, Runnable)和afterExecute(Runnable, Throwable)方法,这些方法在每个任务执行之前和之后调用。这些可用于操纵执行环境;例如,重新初始化 ThreadLocals、收集统计信息或添加日志条目。此外,一旦执行器完全terminated方法来执行需要完成的任何特殊处理。
如果钩子或回调方法抛出异常,内部工作线程可能会失败并突然终止。


队列维护
		方法getQueue()允许访问工作队列以进行监视和调试。强烈建议不要将此方法用于任何其他目的。当大量排队任务被取消时, remove(Runnable)和purge这两个提供的方法可用于协助存储回收


最终确定
	程序中不再引用且没有剩余线程的池 将自动shutdown 。
	如果您想确保即使用户忘记调用shutdown也能回收未引用的池,那么您必须通过设置适当的保持活动时间、使用零核心线程的下限和/或设置allowCoreThreadTimeOut(boolean)来安排未使用的线程最终死亡allowCoreThreadTimeOut(boolean) 。


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

 * class 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();
 *     }
 *   }
 * }
 }
 */
public class ThreadPoolExecutor extends AbstractExecutorService {
    /**
     * 主池控制状态 ctl 是一个原子整数,
     包装了 两个概念字段 
     		workerCount,表示线程的有效数量
        runState,表示是否正在运行,关闭等状态;为了将它们包装成一个int,我们将workerCount限制为(2^29 )-1(约 5 亿)个线程,而不是 (2^31)-1(20 亿)个线程。
        如果将来出现这个问题,可以将该变量更改为 AtomicLong,并调整下面的移位/掩码常量。但在需要之前,使用 int 的代码会更快、更简单。 
        workerCount 是已允许启动且不允许停止的工作线程数。
        该值可能会暂时不同于活动线程的实际数量,例如,当 ThreadFactory 在被请求时无法创建线程时,以及退出线程在终止之前仍在执行时。
        用户可见的池大小被报告为工作集的当前大小。 
        runState 提供主要的生命周期控制,取值如下: 
        RUNNING:接受新任务并处理排队任务 
        SHUTDOWN:不接受新任务,但处理排队任务 
        STOP:不接受新任务,不处理排队任务,并中断正在进行的任务 
        TIDYING:所有任务都已终止, workerCount 为零,线程转换到状态  TIDYING 将运行 terminated() 钩子方法 
        TERMINATED:终止()已完成 
        
        这些值之间的数字顺序很重要,以允许有序比较。 runState 随着时间的推移单调增加,但不需要达到每个状态。
        转换为: 
        RUNNING -> SHUTDOWN 在调用 shutdown() 时,可能隐式地在 Finalize() 中
        (RUNNING 或 SHUTDOWN) -> STOP 在调用 shutdownNow() 时 
        SHUTDOWN -> TIDYING 当队列和池都为空时
        STOP -> TIDYING当池为空时 
        TIDYING -> TERMINATED 当terminated() 钩子方法完成时 
        
        在awaitTermination()中等待的线程将在状态达到TERMINATED时返回。
        检测从 SHUTDOWN 到 TIDYING 的转换并不像您想象的那么简单,因为队列在非空后可能会变空,在 SHUTDOWN 状态期间反之亦然,只有当我们看到它是空的之后,我们才发现workerCount是0,我们才能终止(有时需要重新检查下文)。

     */
  
  	// ctl 的高 3 位 表示线程池的 状态, 低29位表示线程池中正在运行的线程个数
    private final AtomicInteger ctl = new AtomicInteger(ctlOf(RUNNING, 0));   
    private static final int COUNT_BITS = Integer.SIZE - 3;                // 32-3 = 29位的常量
  	// 0001 1111 1111 1111 1111 1111 1111 1111
    private static final int CAPACITY   = (1 << COUNT_BITS) - 1;					// 1左移29位 - 1 , 约5亿,最大的线程数

    // runState is stored in the high-order bits
  
// RUNNING <  SHUTDOWN <  STOP <  TIDYING < TERMINATED 
  
  	//1010 0000 0000 0000 0000 0000 0000 0000
    private static final int RUNNING    = -1 << COUNT_BITS;  // RUNNING 正在运行,接受新任务并处理 排队任务
    //0000 0000 0000 0000 0000 0000 0000 0000
    private static final int SHUTDOWN   =  0 << COUNT_BITS;  // SHUTDOWN 线程池不接受任务  但是队列中的任务可以继续执行
    //0010 0000 0000 0000 0000 0000 0000 0000
    private static final int STOP       =  1 << COUNT_BITS;  // STOP 线程池不接受任务  不处理排队任务  且中断正在处理的任务
    //0100 0000 0000 0000 0000 0000 0000 0000
    private static final int TIDYING    =  2 << COUNT_BITS; // TIDYING 状态下会触发钩子函数terminated(),默认是个空函数,可以重写实现逻辑
              // 当所有的任务已终止,workerCount数量为 0 ,线程池会变为 TIDYING 状态
              // SHUTDOWN 状态的线程池,当所有任务都执行完时,线程池会变为 TIDYING 状态
              // STOP 状态的线程池,当所有正在执行任务都终止,线程池会变为 TIDYING 状态
   //0110 0000 0000 0000 0000 0000 0000 0000
    private static final int TERMINATED =  3 << COUNT_BITS;  // TERMINATED  线程池结束,所有钩子方法【需要用户实现的方法】也执行结束
						//TIDYING 状态下的线程池,回调钩子函数 terminated() 时,状态由此变成 TERMINATED
  
    /*   0110 0000 0000 0000 0000 0000 0000 0000/...(c)
     * & 1110 0000 0000 0000 0000 0000 0000 0000 = (~(0001 1111 1111 1111 1111 1111 1111 1111))
     * = 0110 0000 0000 0000 0000 0000 0000 0000
     */
    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; }       // 将线程的最高3位  和 低29位  组合成 一个 int 数,就是 ctl 值

    /*
     * Bit field accessors that don't require unpacking ctl.
     * These depend on the bit layout and on workerCount being never negative.
     */

    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; }

    /**
     * Attempts to CAS-increment the workerCount field of ctl.
     */
    private boolean compareAndIncrementWorkerCount(int expect) {     return ctl.compareAndSet(expect, expect + 1); }

    /**
     * Attempts to CAS-decrement the workerCount field of ctl.
     */
    private boolean compareAndDecrementWorkerCount(int expect) {     return ctl.compareAndSet(expect, expect - 1); }

    /**
     * 减少 ctl 的 workerCount 字段。仅在线程突然终止时才调用此函数。其他递减在 getTask 中执行。
     */
    private void decrementWorkerCount() {    do {} while (! compareAndDecrementWorkerCount(ctl.get())); }

    /**
     * 队列用于保存任务并移交给工作线程。
     */
    private final BlockingQueue<Runnable> workQueue;

    /**
     * 锁
     */
    private final ReentrantLock mainLock = new ReentrantLock();

    /**
     * 包含池中所有工作线程的集合。仅当持有 mainLock 时才可访问。
     */
    private final HashSet<Worker> workers = new HashSet<Worker>();

    /**
     * 支持awaitTermination的等待条件
     */
    private final Condition termination = mainLock.newCondition();

    /**
     * Tracks largest attained pool size. Accessed only under mainLock.
     */
    private int largestPoolSize;

    /**
     * Counter for completed tasks. Updated only on termination of
     * worker threads. Accessed only under mainLock.
     */
    private long completedTaskCount;  //线程池完成的任务个数

    /*
     * 所有用户控制参数都声明为易失性,以便正在进行的操作基于最新值,但不需要锁定,因为没有内部不变量依赖于它们相对于其他操作同步更改。
     */

    /**
     * 新线程工厂
     */
    private volatile ThreadFactory threadFactory;  // 线程工厂

    /**
     * 处理程序在执行中饱和或关闭时调用
     */
    private volatile RejectedExecutionHandler handler;  // 拒绝策略

    /**
     * 等待工作的空闲线程的超时(以纳秒为单位)。当存在的线程数量超过 corePoolSize 或允许CoreThreadTimeOut 时,线程将使用此超时。
     * 否则他们将永远等待新工作
     */
    private volatile long keepAliveTime;  //  要多久还拿不到任务 就线程销毁

    /**
     * 如果为 false(默认),核心线程即使在空闲时也保持活动(存活、不销毁)态。
     * 如果为 true,则核心线程使用 keepAliveTime 来超时等待工作。
     */
    private volatile boolean allowCoreThreadTimeOut;  // 核心线程是不是要销毁(默认false,不销毁)

    /**
     * 核心池大小是保持活动状态的最小工作线程数(并且不允许超时等),除非设置了allowCoreThreadTimeOut,在这种情况下最小值为零。
     */
    private volatile int corePoolSize;

    /**
     * 最大池大小。请注意,实际最大值在内部受容量限制。
     */
    private volatile int maximumPoolSize;

    /**
     * 默认拒绝执行处理程序
     */
    private static final RejectedExecutionHandler defaultHandler =
        new AbortPolicy();

    /**
     * shutdown 和 shutdownNow 调用者需要Permission。
     */
    private static final RuntimePermission shutdownPerm = new RuntimePermission("modifyThread");

    /* 执行 finalizer 时要使用的上下文,或者为 null。 */
    private final AccessControlContext acc;

  
  /*
  	构造函数	
  */
  public ThreadPoolExecutor(int corePoolSize,
                              int maximumPoolSize,
                              long keepAliveTime,
                              TimeUnit unit,
                              BlockingQueue<Runnable> workQueue) {
        this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
             Executors.defaultThreadFactory(), defaultHandler);
    }

  
    public ThreadPoolExecutor(int corePoolSize,
                              int maximumPoolSize,
                              long keepAliveTime,
                              TimeUnit unit,
                              BlockingQueue<Runnable> workQueue,
                              ThreadFactory threadFactory) {
        this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
             threadFactory, defaultHandler);
    }

    
    public ThreadPoolExecutor(int corePoolSize,
                              int maximumPoolSize,
                              long keepAliveTime,
                              TimeUnit unit,
                              BlockingQueue<Runnable> workQueue,
                              RejectedExecutionHandler handler) {
        this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
             Executors.defaultThreadFactory(), handler);
    }

   
    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;
    }


// 一些 set get  的方法

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

    public ThreadFactory getThreadFactory() {
        return threadFactory;
    }


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

    public RejectedExecutionHandler getRejectedExecutionHandler() {
        return handler;
    }


    public void setCorePoolSize(int corePoolSize) {
        if (corePoolSize < 0)
            throw new IllegalArgumentException();
        int delta = corePoolSize - this.corePoolSize;
        this.corePoolSize = corePoolSize;
        if (workerCountOf(ctl.get()) > corePoolSize)
            interruptIdleWorkers();
        else if (delta > 0) {
            int k = Math.min(delta, workQueue.size());
            while (k-- > 0 && addWorker(null, true)) {
                if (workQueue.isEmpty())
                    break;
            }
        }
    }

    public int getCorePoolSize() {
        return corePoolSize;
    }

    public boolean prestartCoreThread() {
        return workerCountOf(ctl.get()) < corePoolSize &&
            addWorker(null, true);
    }

    void ensurePrestart() {
        int wc = workerCountOf(ctl.get());
        if (wc < corePoolSize)
            addWorker(null, true);
        else if (wc == 0)
            addWorker(null, false);
    }

    public int prestartAllCoreThreads() {
        int n = 0;
        while (addWorker(null, true))
            ++n;
        return n;
    }

    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;
            if (value)
                interruptIdleWorkers();
        }
    }

    public void setMaximumPoolSize(int maximumPoolSize) {
        if (maximumPoolSize <= 0 || maximumPoolSize < corePoolSize)
            throw new IllegalArgumentException();
        this.maximumPoolSize = maximumPoolSize;
        if (workerCountOf(ctl.get()) > maximumPoolSize)
            interruptIdleWorkers();
    }

    
    public int getMaximumPoolSize() {
        return maximumPoolSize;
    }

   
    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;
        if (delta < 0)
            interruptIdleWorkers();
    }

    public long getKeepAliveTime(TimeUnit unit) {
        return unit.convert(keepAliveTime, TimeUnit.NANOSECONDS);
    }

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


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

   
    public void purge() {
        final BlockingQueue<Runnable> q = workQueue;
        try {
            Iterator<Runnable> it = q.iterator();
            while (it.hasNext()) {
                Runnable r = it.next();
                if (r instanceof Future<?> && ((Future<?>)r).isCancelled())
                    it.remove();
            }
        } catch (ConcurrentModificationException fallThrough) {
            // Take slow path if we encounter interference during traversal.
            // Make copy for traversal and call remove for cancelled entries.
            // The slow path is more likely to be O(N*N).
            for (Object r : q.toArray())
                if (r instanceof Future<?> && ((Future<?>)r).isCancelled())
                    q.remove(r);
        }

        tryTerminate(); // In case SHUTDOWN and now empty
    }

   
    public int getPoolSize() {
        final ReentrantLock mainLock = this.mainLock;
        mainLock.lock();
        try {
            // Remove rare and surprising possibility of
            // isTerminated() && getPoolSize() > 0
            return runStateAtLeast(ctl.get(), TIDYING) ? 0
                : workers.size();
        } finally {
            mainLock.unlock();
        }
    }

    public int getActiveCount() {
        final ReentrantLock mainLock = this.mainLock;
        mainLock.lock();
        try {
            int n = 0;
            for (Worker w : workers)
                if (w.isLocked())
                    ++n;
            return n;
        } finally {
            mainLock.unlock();
        }
    }

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

  
    public long getTaskCount() {
        final ReentrantLock mainLock = this.mainLock;
        mainLock.lock();
        try {
            long n = completedTaskCount;
            for (Worker w : workers) {
                n += w.completedTasks;
                if (w.isLocked())
                    ++n;
            }
            return n + workQueue.size();
        } finally {
            mainLock.unlock();
        }
    }

  
    public long getCompletedTaskCount() {
        final ReentrantLock mainLock = this.mainLock;
        mainLock.lock();
        try {
            long n = completedTaskCount;
            for (Worker w : workers)
                n += w.completedTasks;
            return n;
        } finally {
            mainLock.unlock();
        }
    }

   
    public String toString() {
        long ncompleted;
        int nworkers, nactive;
        final ReentrantLock mainLock = this.mainLock;
        mainLock.lock();
        try {
            ncompleted = completedTaskCount;
            nactive = 0;
            nworkers = workers.size();
            for (Worker w : workers) {
                ncompleted += w.completedTasks;
                if (w.isLocked())
                    ++nactive;
            }
        } finally {
            mainLock.unlock();
        }
        int c = ctl.get();
        String rs = (runStateLessThan(c, SHUTDOWN) ? "Running" :
                     (runStateAtLeast(c, TERMINATED) ? "Terminated" :
                      "Shutting down"));
        return super.toString() +
            "[" + rs +
            ", pool size = " + nworkers +
            ", active threads = " + nactive +
            ", queued tasks = " + workQueue.size() +
            ", completed tasks = " + ncompleted +
            "]";
    }

    /* Extension hooks */

  
    protected void beforeExecute(Thread t, Runnable r) { }

   
    protected void afterExecute(Runnable r, Throwable t) { }

   
    protected void terminated() { }

  
  // 拒绝策略 内部类
    
    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);
            }
        }
    }
}
理论知识
  1. 核心和最大池大小:ThreadPoolExecutor将根据 corePoolSize 和 MaximumPoolSize 设置的边界自动调整池大小。

    1. 当在方法execute(Runnable)中提交 新任务并且 运行的线程 少于corePoolSize时,即使 其他工作线程处于空闲状态,会创建一个新线程来处理该请求。
    2. 如果运行的线程数大于 corePoolSize 但小于 maxPoolSize,则仅当队列已满时 才会创建新线程。
    3. 通过将 corePoolSize 和 MaximumPoolSize 设置为相同,可以创建固定大小的线程池。通过将 MaximumPoolSize 设置为本质上无界的值(例如Integer.MAX_VALUE ,可以允许池容纳任意数量的并发任务。
    4. 最典型的是,核心和最大池大小仅在构造时设置,但也可以使用setCorePoolSize和setMaximumPoolSize动态更改。
  2. 创建新线程
    新线程是使用ThreadFactory创建的。如果没有另外指定,则使用 默认的线程工厂 ,它创建的线程都位于同一 ThreadGroup 中,并具有相同的NORM_PRIORITY优先级和非守护进程状态。通过提供不同的 ThreadFactory,您可以更改线程的名称、线程组、优先级、守护进程状态等。

    1. 如果ThreadFactory在通过从newThread返回 null 表示未能创建线程,则执行程序将继续,但可能无法执行任何任务。
    2. 线程应该拥有“modifyThread” RuntimePermission 。如果工作线程或使用该池的其他线程不拥有此权限,则服务可能会降级:配置更改可能无法及时生效,并且关闭池可能仍处于可能终止但未完成的状态。
  3. 队列

    1. 任何BlockingQueue都可用于传输和保存已提交的任务。该队列的使用与池大小相互作用:

      1. 如果运行的线程少于 corePoolSize,则 Executor 始终倾向于添加新线程而不是排队。
      2. 如果 corePoolSize 或更多线程正在运行,Executor 总是更喜欢对请求进行排队而不是添加新线程。
      3. 如果请求无法排队,则会创建一个新线程,除非这超出了 MaximumPoolSize,在这种情况下,该任务将被拒绝。
    2. 排队的一般策略有以下三种:

      1. 直接切换。工作队列的一个不错的默认选择是 SynchronousQueue ,它将任务交给线程而不以其他方式保留它们。在这里,如果没有线程可以立即运行任务,则尝试对任务进行排队将会失败,因此将构造一个新线程。

        此策略可避免在处理可能具有内部依赖性的请求集时发生锁定。

        直接切换通常需要无限制的 MaximumPoolSizes 以避免拒绝新提交的任务。

        这反过来又承认当命令到达的平均速度继续快于处理速度时,线程可能会无限增长。

      2. 无界队列。当所有 corePoolSize 线程都忙时,使用无界队列(例如没有预定义容量的LinkedBlockingQueue )将导致新任务在队列中等待。因此,将不会创建超过 corePoolSize 的线程。 (因此,maximumPoolSize 的值不会产生任何影响。)当每个任务完全独立于其他任务时,这可能是合适的,因此任务不会影响彼此的执行;例如,在网页服务器中。虽然这种排队方式对于平滑请求的瞬时突发很有用,但它承认当命令平均到达速度继续快于处理速度时,工作队列可能会无限增长。

      3. 有界队列。有界队列(例如ArrayBlockingQueue )在与有限的 MaximumPoolSizes 一起使用时有助于防止资源耗尽,但可能更难以调整和控制。队列大小和最大池大小可以相互权衡:使用大队列和小池可以最大限度地减少 CPU 使用率、操作系统资源和上下文切换开销,但可能会导致人为降低吞吐量。如果任务经常阻塞(例如,如果它们受 I/O 限制),系统可能会为比您允许的更多线程安排时间。使用小队列通常需要更大的池大小,这会使 CPU 更加繁忙,但可能会遇到不可接受的调度开销,这也会降低吞吐量

  4. 任务的拒接策略:当 Executor 关闭时,以及当 Executor 对最大线程和工作队列容量使用有限界限并且饱和时,在方法execute(Runnable)中提交的新任务将被拒绝。无论哪种情况, execute方法都会调用其RejectedExecutionHandler的RejectedExecutionHandler.rejectedExecution(Runnable, ThreadPoolExecutor)方法。提供了四种预定义的处理程序策略:

    1. 在默认的ThreadPoolExecutor.AbortPolicy中,处理程序在拒绝时抛出运行时RejectedExecutionException 。

    2. 在ThreadPoolExecutor.CallerRunsPolicy中,调用execute本身的线程运行任务。这提供了一个简单的反馈控制机制,将减慢新任务提交的速度。

    3. 在ThreadPoolExecutor.DiscardPolicy中,无法执行的任务将被简单地丢弃。

    4. 在ThreadPoolExecutor.DiscardOldestPolicy中,如果执行器没有关闭,则工作队列头部的任务将被丢弃,然后重试执行(可能会再次失败,导致重复执行)。

线程池执行流程
execute

image-20231203204843300

  /**
     在将来的某个时间执行给定的任务。
     该任务可以在新线程或现有池线程中执行。
     如果任务无法提交执行,无论是因为该执行器已关闭还是因为其容量已达到,则该任务将由当前的RejectedExecutionHandler处理
     */
    public void execute(Runnable command) {
        if (command == null)
            throw new NullPointerException();
        /*
         * Proceed in 3 steps:
         * 1.如果正在运行的线程少于 corePoolSize,请尝试使用给定命令启动一个新线程作为其第一个任务。
         		对 addWorker 的调用以原子方式检查 runState 和workerCount,从而通过返回 false 来防止在不应该添加线程时添加线程的错误警报。 
         * 2.如果任务可以成功排队,那么我们仍然需要仔细检查是否应该添加线程(因为自上次检查以来现有线程已死亡),或者自进入此方法以来池已关闭
         		因此,我们重新检查状态,并在必要时回滚排队(如果停止),或者启动一个新线程(如果没有)。 
         * 3.如果我们无法将任务排队,那么我们尝试添加一个新线程。如果失败,我们就知道我们已关闭或饱和,因此拒绝该任务。
         */
        int c = ctl.get();
 // 1
      if (workerCountOf(c) < corePoolSize) {    // workerCountOf(c) 计算线程池的工作线程数   <  核心线程数
        
            if (addWorker(command, true))					// 要是成功启动一个新线程作为其第一个任务,就是 true   创建核心线程 并直接 return
                return;
            c = ctl.get();												// 否则再次获取ctl 的值
        }
    
 // 2     
       //  workerCountOf(c) 再次计算线程池的工作线程数   >=   核心线程数   或者 线程池被暂停了
        if (isRunning(c) && workQueue.offer(command)) {//上面的if没有return 并且 此时线程池处于运行 且 workQueue.offer(command) 任务已经入队
            int recheck = ctl.get();							//再次重新获取 ctl 的值
            if (!isRunning(recheck) && remove(command)) 
             // isRunning(recheck) == false  表明 线程不是运行状态了    并且remove(command)  移除成功 
                reject(command); //执行拒绝策略
            else if (workerCountOf(recheck) == 0)
        // 要是 工作的线程数 workerCountOf(recheck) == 0,表示此时线程池空闲 ,但是线程池必须要有工作的线程,就要就创建无任务的非核心线程
                addWorker(null, false);
        }
 //3 
      // workerCountOf(c) 计算线程池的工作线程数   >=   核心线程数   且 workQueue.offer(command) 失败即 阻塞队列满了, 线程池 不处于运行
        else if (!addWorker(command, false))   // 就是从 false 创建 非核心线程
            reject(command);           // 执行拒绝策略
    }




//只有这里是 running 才满足  c < SHUTDOWN;        
private static boolean isRunning(int c) {
       return c < SHUTDOWN;
}


public boolean remove(Runnable task) {
//通过阻塞队列 移除 任务
  boolean removed = workQueue.remove(task);
//尝试结束线程池(不一定成功)
   tryTerminate(); // In case SHUTDOWN and now empty
//返回移除的结果
   return removed;
}


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

//当execute无法接受任务时, ThreadPoolExecutor可能调用的方法。
//当没有更多线程或队列槽可用(因为超出了它们的边界)或者执行器关闭时,可能会发生这种情况。
//在没有其他替代方案的情况下,该方法可能会抛出未经检查的RejectedExecutionException ,该异常将传播到execute的调用者。
    			
public interface RejectedExecutionHandler {
    void rejectedExecution(Runnable r, ThreadPoolExecutor executor);  // 具体实现 见各个拒绝策略的的实现步骤【见下】
}
					
					
// CallerRunsPolicy  被拒绝任务的处理程序,直接在execute方法的调用线程中运行被拒绝的任务,除非执行器已关闭,在这种情况下任务将被丢弃。
					  public static class CallerRunsPolicy implements RejectedExecutionHandler {
                public CallerRunsPolicy() { }
                public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
                // 在调用者的线程中执行任务 r,除非执行器已关闭,在这种情况下任务将被丢弃
                    if (!e.isShutdown()) {
                        r.run();
                    }
                }
            }
					
// AbortPolicy    抛出RejectedExecutionException的被拒绝任务的处理程序。
					    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) {
                       // 不执行任何操作,这会导致丢弃任务 r。
                    }
               }
//DiscardOldestPolicy  被拒绝任务的处理程序,丢弃最旧的未处理请求,然后重试execute ,除非执行器被关闭,在这种情况下任务将被丢弃
               public static class DiscardOldestPolicy implements RejectedExecutionHandler {
                  public DiscardOldestPolicy() { }
                  public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
              //获取并忽略 执行器本来要执行的下一个任务(如果该任务立即可用),然后重试执行任务 r,除非执行器关闭,在这种情况下任务 r 将被丢弃。
                      if (!e.isShutdown()) {
                          e.getQueue().poll();
                          e.execute(r);
                      }
                  }
    						}  
addWorker()

image-20231203205226946

/* 
     检查是否可以根据当前池状态和给定边界(核心或最大值)添加新工作线程。
     如果是这样,则相应地调整工作线程数,并且如果可能的话,将创建并启动一个新工作线程,并将firstTask作为其第一个任务运行。
     如果池已停止或符合关闭条件,此方法将返回 false。
     如果线程工厂在询问时未能创建线程,它也会返回 false。
     如果线程创建失败,无论是由于线程工厂返回 null,还是由于异常(通常是 Thread.start() 中的 OutOfMemoryError),我们都会干净地回滚。
 
 
   core:ture表明创建核心线程,false:创建非核心线程             
   firstTask:不为nuLL,表明是用户提交的任务,为nuLL,表明是线程池调用的 
     不为 null  先运行提交的任务,再运行阻塞队列的任务
     为null ,就直接去阻塞队列拿任务,方式有:
      1、超时获取 (超时死亡)
      2、阻塞获取(一定获取才结束)
 */
 private boolean addWorker(Runnable firstTask, boolean core) {
        retry:
        for (;;) { // 死循环
            int c = ctl.get(); // 获取 ctl 
            int rs = runStateOf(c); //获取线程池的运行状态

            // Check if queue empty only if necessary.
            if (rs >= SHUTDOWN &&        !(rs == SHUTDOWN && firstTask == null &&!workQueue.isEmpty()))
              // 非运行状态              !(是停止状态 且 此时没有用户提交的任务只处理阻塞队列的任务 且  任务队列不是空)              
                return false; 

          /*
          处于此处:
          1、线程池处于 运行状态
          2、线程池处于 SHUTDOWN  且  非用户提交的任务(firstTask == null)  且   任务队列不是空
          */
            for (;;) {   // 死循环: 目的 给工作线程数 +1
                int wc = workerCountOf(c);  // 获取 运行的线程数
                if (wc >= CAPACITY    ||   wc >= (core ? corePoolSize : maximumPoolSize)) 
                   // 线程数超过 容量   或者       线程数大于核心或者最大线程数
                    return false;                     // 返回 false
                if (compareAndIncrementWorkerCount(c)) // cas 得  将运行的线程个数 +1 
                   /*
                    尝试对 ctl 的 workerCount 字段进行 CAS 递增。
                    private boolean compareAndIncrementWorkerCount(int expect) {
                        return ctl.compareAndSet(expect, expect + 1); 
      ==> 底层: unsafe.compareAndSwapInt(this, valueOffset, expect, update);如果当前值==预期值,则自动将该值设置为给定的更新值。
                    }
                    */
                  // cas 的操作成功   结束,退出 for 循环
                    break retry;
              // 一旦 cas 的操作失败   
                c = ctl.get();  // 重新获取 ctl
                if (runStateOf(c) != rs)  // 要是运行状态改变了
                  // 跳过当前循环, 进行下一次循环
                    continue retry;       
                // else CAS failed due to workerCount change; retry inner loop
            }
        }

   /*
   两个for 循环的作用
     到达此处:
     1、判断是否可以执行add
     2、给线程数工作线程数 +1
   */
   
   // work 是否  启动  成功
        boolean workerStarted = false;
   // work 是否  添加  成功
        boolean workerAdded = false;
        Worker w = null;
        try {
          //创建 worker  ,
            w = new Worker(firstTask);
          // 由 Worker 创建线程
            final Thread t = w.thread;
          //  线程创建成功
            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());  // 获取ctl 线程池的状态

                    if (rs < SHUTDOWN || (rs == SHUTDOWN && firstTask == null)) {
                      // 运行  或者   阻塞但是没有新的任务
                      /*
                      	运行到此处:
                      	1、线程池为 运行状态
                      或者
                      	2、状态为 SHUTDOWN,并且是在 阻塞队列里面获取的任务
                      */
                        if (t.isAlive()) // precheck that t is startable   
                          // isAlive  是一个 native 方法 表示测试该线程是否存活。如果线程已启动且尚未死亡,则该线程处于活动状态。
                            throw new IllegalThreadStateException();
                       //  线程未死
                      	workers.add(w);// 将创建的 worker 放到 池中所有工作线程的集合中
                        int s = workers.size(); // 得到集合的大小
                        if (s > largestPoolSize)  
                            largestPoolSize = s; // 池最大容量进行更新
                        workerAdded = true;  //work 添加  成功
                    }
                } finally {
                    mainLock.unlock(); // 解锁
                }
                if (workerAdded) { //线程 添加  成功
                    t.start(); // 启动线程
  //【 此处只知道线程启动任务,但是线程任务执行完之后怎么办===> 此时要去 worker 中查看 】
                    workerStarted = true; // 线程启动 成功
                }
            }
        } finally {
            if (! workerStarted) // 线程启动 失败
              
                addWorkerFailed(w); //进行回滚 操作
        }
        return workerStarted; // 线程是否  启动  成功
    }

addWorkerFailed

image-20231203205410231

/*
		回滚工作线程的创建。 
		将 Worker 从 Workers 移除(如果存在)
    减少 Worker 数量
    重新检查终止情况,以防该 Worker 的存在阻碍终止
*/
private void addWorkerFailed(Worker w) {
        final ReentrantLock mainLock = this.mainLock;
        mainLock.lock();
        try {
            if (w != null)
                workers.remove(w); // worker 不为 null 那么就移除worker
            decrementWorkerCount(); // cas 的方式减少  工作的的 个数
            // 尝试关闭线程,移除一个线程,可能会使workers为空,所以尝试关闭,但是不一定关闭成功
          	tryTerminate();
        } finally {
            mainLock.unlock();
        }
    }

    /**
     * 减少 ctl 的workerCount 字段。仅在线程突然终止时才调用此函数
     */
    private void decrementWorkerCount() {
        do {} while (! compareAndDecrementWorkerCount(ctl.get()));
    }
内部类Worker

image-20231203205910451

   /**
     * Worker 类主要维护运行任务的线程的中断控制状态,以及其他次要的簿记。
     此类机会性地扩展 AbstractQueuedSynchronizer 以简化获取和释放围绕每个任务执行的锁。
     这可以防止旨在唤醒等待任务的工作线程的中断,而不是中断正在运行的任务。
     我们实现一个简单的不可重入互斥锁而不是使用 ReentrantLock,因为我们不希望工作任务在调用像 setCorePoolSize 这样的池控制方法时能够重新获取锁。
     此外,为了在线程实际开始运行任务之前抑制中断,我们将锁定状态初始化为负值,并在启动时清除它(在 runWorker 中)。
     */

/*
	继承了  AQS     表明这个任务就是一把锁
	实现了 Runnable 表明Thread 类可以启动调用这个 work 
	更加便于管理任务
*/
    private final class Worker extends AbstractQueuedSynchronizer  implements Runnable {
        /**
         * This class will never be serialized, but we provide a
         * serialVersionUID to suppress a javac warning.
         */
        private static final long serialVersionUID = 6138294804551838833L;

        /** Thread this worker is running in.  Null if factory fails. */
        final Thread thread; // 工作的线程
        /** Initial task to run.  Possibly null. */
        Runnable firstTask;  // 运行的初始任务
        /** Per-thread task counter */
        volatile long completedTasks;  // 每个线程任务的计数器

        /**
         * Creates with given first task and thread from ThreadFactory.
         * @param firstTask the first task (null if none)
         */
        Worker(Runnable firstTask) {
          // 设置为 -1 ,表明这个任务 不允许被中断
            setState(-1); // inhibit interrupts until runWorker
          // 设置任务的执行目标
            this.firstTask = firstTask;
          // 调用线程工厂创建线程
            this.thread = getThreadFactory().newThread(this);this 就是 Worker}

【任务在线程中的执行的入口】
        /** Delegates main run loop to outer runWorker  */
        public void run() {
            runWorker(this);
        }

        // Lock methods
        //
        // The value 0 represents the unlocked state.
        // The value 1 represents the locked state.

        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) {
            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) {
                }
            }
        }
    }

runWorker

image-20231203205641149

/*
mian worker程序运行循环。重复地从队列中获取任务并执行它们,同时处理一些问题:

		1.我们可以从 初始任务 开始,在这种情况下,我们不需要获得第一个任务。否则,只要pool正在运行,我们就会从getTask获取任务。如果它返回null,则由于池状态或配置参数更改,工作线程退出。
			其他退出是由异常抛出引起的外部代码,在这种情况下completedsudden保持,这通常导致processWorkerExit替换该线程。
		2.在运行任何任务之前,需要获得锁以防止任务执行时其他池中断,然后我们确保除非池停止,否则该线程没有中断集。
 		3.每个任务运行之前都要调用beforeExecute,这可能会抛出一个异常,在这种情况下,我们导致线程死亡(使用completedsudden为true打破循环),而不处理任务。
		4.假设beforeExecute正常完成,我们运行任务,收集其抛出的任何异常发送给afterExecute。我们分别处理RuntimeException, Error(这两个规范都保证我们捕获)和任意Throwables。因为我们不能在Runnable.run中重新抛出Throwables,所以我们在退出时(到线程的UncaughtExceptionHandler)将它们包装在Errors中。任何抛出的异常都会保守地导致线程死亡。
		5. 在task.run完成后,调用afterExecute,这也可能抛出异常,这也会导致线程死亡。根据JLS第14.20节,即使task.run抛出,这个异常也会生效。
		
		异常机制的最终效果是,afterExecute和线程的UncaughtExceptionHandler拥有关于用户代码遇到的任何问题的尽可能准确的信息。
*/
final void runWorker(Worker w) {
    Thread wt = Thread.currentThread(); // 拿到当前执行的线程
    Runnable task = w.firstTask;// 从 worker 中 获取 用户提交的任务
    w.firstTask = null;		// 对队列中的任务置为null
  	w.unlock(); // allow interrupts
   	//解锁:就是将 state  的值 变为 0 ,【对应之前创建 Worker的(worker(...){... setState(-1)...})】 也就是说他是可以 中断 的
  	// 从构造器创建 到 此处使用 是不允许 中断 的,因为要设置一些准备操作 
  /*
  
  			 public void unlock()      { release(1); }
  
         public final boolean release(int arg) {
              if (tryRelease(arg)) {
                  Node h = head;
                  if (h != null && h.waitStatus != 0)
                      unparkSuccessor(h);
                  return true;
              }
              return false;
          }
          
          
  		    protected boolean tryRelease(int unused) {
              setExclusiveOwnerThread(null);
              setState(0);   //就是将 state  的值 变为 0
              return true;
       		 }
  */
  	//表示任务是否正常执行完成
    boolean completedAbruptly = true;  //true 表示任务 未能  正常执行完成
    try {
      // 循环【重点】
      // 一旦 getTask 阻塞 就表明 阻塞队列没有任务,线程池处于空闲状态,线程也是空闲的
        while (task != null || (task = getTask()) != null) {
          //  有任务 : 来源于  用户提交的任务 或者 调用getTask() 从阻塞队列中拿到任务
            w.lock();
            // 如果池正在停止,请确保线程被中断;如果没有,请确保线程不被中断。这需要在第二种情况下重新检查以处理 shutdownNow 竞争,同时清除中断
            if ((runStateAtLeast(ctl.get(), STOP) || (Thread.interrupted() && runStateAtLeast(ctl.get(), STOP))) 
                																																									&& !wt.isInterrupted())
             // 线程状态 > STOP  || ( 线程已经被中断 && 线程状态 > stop ) &&     获取当前线程状态判断线程是否已经被中断了  false 未被打断
                
              wt.interrupt(); //中断线程
            try {
                beforeExecute(wt, task); //任务执行前的钩子函数
                Throwable thrown = null;
                try {
                    task.run();// 执行任务
                  /*
                  Runnable接口应该由其实例旨在由线程执行的任何类来实现。该类必须定义一个名为run的无参数方法。
            该接口旨在为希望在活动时执行代码的对象提供通用协议。例如, Runnable是由Thread类实现的。处于活动状态仅仅意味着线程已经启动并且尚未停止。
                  此外, Runnable提供了使类处于活动状态而不需要子类化Thread方法。
                  实现Runnable的类可以通过实例化Thread实例并将其自身作为目标传递来运行,而无需子类化Thread 。
                  在大多数情况下,如果您只计划重写run()方法而不重写其他Thread方法,则应使用Runnable接口。
                  这很重要,因为除非程序员打算修改或增强类的基本行为,否则不应对类进行子类化。
             
                  public interface Runnable {
                  
                  当使用实现接口Runnable的对象创建线程时,启动线程会导致在该单独执行的线程中调用该对象的run方法。
                  方法run的一般契约是它可以采取任何操作
                      public abstract void 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; // 任务执行完之后就 置null 
                w.completedTasks++;// 完成的任务数++ 
                w.unlock();//解锁的目的: 任务执行完,线程处于空闲状态
            }
        }
        completedAbruptly = false;   //fasle 表示任务  正常执行完成
    } finally {
        processWorkerExit(w, completedAbruptly);// 任务的后续处理: worker退出流程
    }
}


/*
根据当前的配置设置,对任务执行阻塞或定时等待,或者如果该工作线程由于以下原因必须退出,则返回 null:
	1. 工作线程数量超过 maximumPoolSize(由于调用了 setMaximumPoolSize)。
  2. 池已停止。 
  3. 池已关闭且队列为空。 
  4. 该worker等待任务超时,超时的worker在定时等待前后都会被终止(即allowCoreThreadTimeOut || workerCount > corePoolSize ),并且如果队列非空,则该worker不是池中的最后一个线程
*/

getTask

image-20231203205737842

 private Runnable getTask() {
        boolean timedOut = false; // Did the last poll() time out?  上次任务poll()是不是超时了:默认 false 未超时

        for (;;) {
          // 获取 ctl 值 和 线程池的状态
            int c = ctl.get();
            int rs = runStateOf(c);

            // Check if queue empty only if necessary.
            if (rs >= SHUTDOWN && (rs >= STOP || workQueue.isEmpty())) {
              // 线程池状态 >=  SHUTDOWN && 队列空了,没有任务了   ||  线程池状态  >= STOP
                decrementWorkerCount();//工作线程数--
                return null;
            }
						/*
							1、表明线程池的状态为运行  running 
							2、线程池状态 >= SHUTDOWN && 阻塞队列还有任务
						*/
          // 获取 工作线程的数量
            int wc = workerCountOf(c);

          // Are workers subject to culling?
          // allowCoreThreadTimeOut = false(默认) 核心线程即使在空闲时也保持活动(存活、不销毁)态。
         
          // 任务会不会消亡          核心线程即使在空闲时也保持活动(存活、不销毁)态 || 工作线程的数量 > 核心线程的数量
          
          /*
          allowCoreThreadTimeOut:true表示核心线程可以被回收,false则表示不回收核心线程(默认)
          wc>corePoolS1ze:true表示工作线程数超过核心线程,false表示工作线程数未超过核心线程
          timed == true:
          					表示当前这个线程获取task时 是支持超时机制的,使用queue.poll(XX,XX)
          					第一个参数是时间,第二个参数是时间单位。当获取task超时的情况下,下一次自旋就可能返回null了。
          timed == false:
          					表示当前这个线程获取task时是不支持超时机制的,当前线程会使用带阻塞的queue.take()方法:
					*/
            boolean timed = allowCoreThreadTimeOut || wc > corePoolSize;
					
         
           //第二次之后运行 才会 走这里  此时   工作线程数 > 核心线程数
  /*
          条件1:(wc > maximumPoolSize|| (timed && timed0ut))
          	1.1:wc>maximumPoolS1ze何时会成立?
          			线程池对外提供setMaxinumPoolSize()方法设置最大线程数,所以其他线程会重新设置最大线程数导致该值比初始化的时候大
						1.2:(timed&&timed0ut)条件成立:
								timed为ture,表明允许回收核心线程或者工作线程大于核心线程 (回收的机制就是使用带超时时间的获取任务方法po11,时间一到,返回 nu11)
								timed0ut为ture,表明通过超时获取的任务为null
					条件2:(wc>1 workQueue.isEmpty())
						2.1:wc>1条件成立,说明当前线程池中还有其他线程,当前线程可以直接回收,返回nu11
						2.2:workQueue,isEmpty()前置条件wc==1,条件成立:说明当前任务队列已经空了,最后一个线程,也可以放心的退出。
						
				  条件1 && 条件2为 true 表明当前线程达到回收标准
				  
				  整理一下回收线程的标准:
				  	1、工作线程数大于线程池最大线程数且工作线程数大于1
				  	2、(允许回收核心线程/工作线程大于核心线程)且超时获取任务为nu11,且(工作线程数大于1或队列为空】				  	
*/
            if (
               // 工作线程的数量 > 最大线程的数量 (会有 setMaximumPoolSize 的方法) ||  (任务不会被剔除 && 上次poll()超时了)
              (wc > maximumPoolSize || (timed && timedOut))
                 && 
               // 工作线程的数量 > 1 ||  队列空
              (wc > 1 || workQueue.isEmpty())
               ) {
                
                /*
                设置允许的最大线程数。这会覆盖构造函数中设置的任何值。如果新值小于当前值,多余的现有线程将在下次空闲时终止。
                    public void setMaximumPoolSize(int maximumPoolSize) {
                        if (maximumPoolSize <= 0 || maximumPoolSize < corePoolSize)
                            throw new IllegalArgumentException();
                        this.maximumPoolSize = maximumPoolSize;
                        if (workerCountOf(ctl.get()) > maximumPoolSize)
                            interruptIdleWorkers();
                    }
                    
                    
                     private void interruptIdleWorkers() {
                          interruptIdleWorkers(false);
                      }
                      
                      
                      
                      中断可能正在等待任务的线程(如未锁定所示),以便它们可以检查终止或配置更改。
                      忽略 SecurityExceptions(在这种情况下,某些线程可能保持不间断)。
                       private void interruptIdleWorkers(boolean onlyOne) {
                            final ReentrantLock mainLock = this.mainLock;
                            mainLock.lock();
                            try {
                                for (Worker w : workers) {
                                    Thread t = w.thread;
                                    if (!t.isInterrupted() && w.tryLock()) {
                                        try {
                                            t.interrupt();
                                        } catch (SecurityException ignore) {
                                        } finally {
                                            w.unlock();
                                        }
                                    }
                                    if (onlyOne)
                                        break;
                                }
                            } finally {
                                mainLock.unlock();
                            }
                        }

                */
               
                if (compareAndDecrementWorkerCount(c))  // 此时线程会被回收 cas的方式 将工作线程数 -1
                    return null;  //结束 线程消亡
                continue;  //cas 失败 重新循环
            }

          //第一次运行 时 只走这里
            try {
        Runnable r = timed ? workQueue.poll(keepAliveTime, TimeUnit.NANOSECONDS) : workQueue.take();
             //        任务被剔除   :  超时或者阻塞会抛出异常,                   任务未被剔除 : 一直阻塞到 获取任务或者 返回任务    
                if (r != null)
                    return r;
              //   任务 为  null ,没有获取到任务 表示上次 workQueue.poll() 超时了
                timedOut = true;
            } catch (InterruptedException retry) {
              
             // 出错也表示 没有超时
                timedOut = false;
            }
        }
    }

processWorkerExit

image-20231203205829240

/*
	为垂死的 worker 进行清理和簿记。
	仅从工作线程调用。除非设置了completedAbruptly,否则假定workerCount 已调整为考虑退出。
此方法从工作集中删除线程,如果由于用户任务异常而退出,或者正在运行的工作线程少于 corePoolSize 或队列非空但没有工作线程,则可能会终止池或替换工作线程。
*/
private void processWorkerExit(Worker w, boolean completedAbruptly) {
        if (completedAbruptly) // If abrupt, then workerCount wasn't adjusted
            decrementWorkerCount();  // 要是没完成任务  减少线程池中的线程数量

  //completedAbruptly = fasle   要是完成了任务 
        final ReentrantLock mainLock = this.mainLock;
        mainLock.lock();
        try {
          // 将 worker  执行的任务进行累加
            completedTaskCount += w.completedTasks;
          // 任务队列中删除该任务
            workers.remove(w);
        } finally {
            mainLock.unlock();
        }

        tryTerminate(); // 线程池退出处理

        int c = ctl.get();
        if (runStateLessThan(c, STOP)) { //判断线程池状态是不是 ruunning 或者 shutdown 
            if (!completedAbruptly) {  //  要是完成了任务 
              // 计算当前线程池的工作线程数量
              // 计算当前线程池可以预留的最小的线程数
                int min = allowCoreThreadTimeOut ? 0 : corePoolSize;
                if (min == 0 && !workQueue.isEmpty())
                    min = 1;  //置为1
              //  当前线程池中的运行线程的数量  >= 预留的线程的最小数量 
                if (workerCountOf(c) >= min)
                  // 此时直接return 线程 消亡
                    return; // replacement not needed
            }
          // 线程池中任务执行失败之后,此线程会消亡 并 向线程池中 添加一个线程
          // 当前线程池中的运行线程的数量 < 预留的线程池的最小数量 ,需要往线程池中 添加线程
            addWorker(null, false);
        }
    }

线程池结束流程

当不再使用线程池的时候会进行关闭

关闭的方式:

  1. shutdown():将线程的状态设置为 SHUTDOWN 状态,正在执行的任务会继续执行下去,没有执行任务 就会中断
  2. shutdownNow():将 线程 的状态设置为 STOP 状态,正在执行的任务会 被停止 ,没有执行任务就 直接返回
shutdown

image-20231203204726904

  

    /**
     * 启动有序关闭,其中执行先前提交的任务,但不会接受新任务。如果已经关闭,调用不会产生额外的效果
     * 该方法不等待之前提交的任务完成执行。使用awaitTermination来做到这一点
     */
    public void shutdown() {
        final ReentrantLock mainLock = this.mainLock;
        mainLock.lock();
        try {
          // 检查是不是线程安全的
            checkShutdownAccess();
          // 将线程池的状态设置为 SHUTDOWN
            advanceRunState(SHUTDOWN);
          /*
          将 runState 转换到给定目标,或者如果至少已经是给定目标,则将其保留。
           private void advanceRunState(int targetState) {
                for (;;) {
                    int c = ctl.get();
                     判断线程池的状态是不是 >=  targetState 是的话执行break ,否则  可以 cas 处理 拼得 ctl ,然后 break 
                    if (runStateAtLeast(c, targetState) ||  ctl.compareAndSet(c, ctlOf(targetState, workerCountOf(c))))
                        break;
                }
            }
          */
          // 中断处于空闲状态的工作线程。
            interruptIdleWorkers();
        
      
          // 回调钩子函数
          	onShutdown(); // hook for ScheduledThreadPoolExecutor  钩子方法
        } finally {
            mainLock.unlock();
        }
      // 尝试关闭线程池
        tryTerminate();
    }

   
interruptIdleWorkers

image-20231203204800174

 //中断可能正在等待任务的线程,以便它们可以检查终止或配置更改。忽略 SecurityExceptions(在这种情况下,某些线程可能保持不间断)。
            private void interruptIdleWorkers() {
                interruptIdleWorkers(false);
            }
   //   onlyOne: true 表示只中断一个未执行的任务,反之 全部任务都中断     
             private void interruptIdleWorkers(boolean onlyOne) {
                final ReentrantLock mainLock = this.mainLock;
                mainLock.lock();
                try {
                    for (Worker w : workers) { // 遍历线程池工作的线程集合,中断所有不忙碌的线程中断
                        Thread t = w.thread;
                        // w.tryLock() 尝试加锁成功,表明线程空闲,可以中断,反之线程还在执行任务,无法中断
                        if (!t.isInterrupted() && w.tryLock()) {
                            try {
                            //线程空闲,此处中断
                                t.interrupt();
                            } catch (SecurityException ignore) {
                            } finally {
                                w.unlock();
                            }
                        }
                        if (onlyOne) // true 只中断一个就结束循环
                            break;
                    }
                } finally {
                    mainLock.unlock();
                }
            }
shutdownNow

image-20231203204645084

/**
     * 尝试停止所有正在执行的任务,停止正在等待的任务的处理,并返回正在等待执行的任务的列表。
     * 从此方法返回后,这些任务将从任务队列中排出(删除)。
     * 此方法不等待主动执行的任务终止。使用awaitTermination来做到这一点。
     * 除了尽最大努力尝试停止处理主动执行的任务之外,没有任何保证。此实现通过Thread.interrupt取消任务,因此任何无法响应中断的任务可能永远不会终止。
     */
    public List<Runnable> shutdownNow() {
        List<Runnable> tasks; // 定义一个集合,存放没有执行的任务
        final ReentrantLock mainLock = this.mainLock;
        mainLock.lock();
      // 为什么加锁: 这里面的操作都是对 原子类 ctl 进行的,ctl 是一个全局变量,所以要加锁操作
        try {
            checkShutdownAccess();
          /*
          如果有安全管理器,请确保调用者有权关闭一般线程
          如果通过,还确保允许调用者中断每个工作线程。如果 SecurityManager 特别对待某些线程,即使第一次检查通过,情况也可能不成立。
          
           private void checkShutdownAccess() {
                SecurityManager security = System.getSecurityManager();
                if (security != null) {
                    security.checkPermission(shutdownPerm);
                    final ReentrantLock mainLock = this.mainLock;
                    mainLock.lock();
                    try {
                        for (Worker w : workers)
                            security.checkAccess(w.thread);
                    } finally {
                        mainLock.unlock();
                    }
                }
            }
          */
            advanceRunState(STOP);
          /*
          将 runState 转换到给定目标,或者如果至少已经是给定目标,则将其保留。
            private void advanceRunState(int targetState) {
                for (;;) {
                    int c = ctl.get();
                    if (runStateAtLeast(c, targetState) ||
                        ctl.compareAndSet(c, ctlOf(targetState, workerCountOf(c))))
                        break;
                }
            }
          */
          
          // 中断所有的任务
            interruptWorkers();
    
          
         //  获取所有没有执行的任务集合
            tasks = drainQueue();
          /*
          将任务队列排空到新列表中,通常使用drainTo。但是,如果队列是 DelayQueue 或任何其他类型的队列,其中 poll 或 danceTo 可能无法删除某些元素,则会将它们一一删除。
          
           private List<Runnable> drainQueue() {
                BlockingQueue<Runnable> q = workQueue;
                ArrayList<Runnable> taskList = new ArrayList<Runnable>();
                q.drainTo(taskList);   																从 q 队列中删除所有可用元素并将它们添加到给定集合 taskList  中
                if (!q.isEmpty()) {     //调用方法转移一遍之后, q 不为空,转移失败 这个  阻塞队列的类  没有实现这个方法
                    for (Runnable r : q.toArray(new Runnable[0])) { //手动操作一遍
                        if (q.remove(r))
                            taskList.add(r);
                    }
                }
                return taskList;
            }
            
          */
        } finally {
            mainLock.unlock();
        }
        /*
        核心: 尝试终结线程池
        */
        tryTerminate();
      // 返回没有执行的任务集合
        return tasks;
    }

    public boolean isShutdown() {
        return ! isRunning(ctl.get());
    }

    /**
     * 如果此执行器在shutdown或shutdownNow之后正在终止但尚未完全终止,则返回 true。
     * 此方法对于调试可能很有用。在关闭后足够长的时间内报告返回true可能表明提交的任务已忽略或抑制中断,导致此执行程序无法正确终止
     */
    public boolean isTerminating() {
        int c = ctl.get();
        return ! isRunning(c) && runStateLessThan(c, TERMINATED);
    }

    public boolean isTerminated() {
        return runStateAtLeast(ctl.get(), TERMINATED);
    }
interruptWorkers

image-20231203204700194

 中断所有线程,即使处于活动状态。忽略 SecurityExceptions(在这种情况下,某些线程可能保持不间断)。
        	private void interruptWorkers() {
              final ReentrantLock mainLock = this.mainLock;
              mainLock.lock();
              try {
                  for (Worker w : workers)  遍历工作线程集合进 中断
                      w.interruptIfStarted();
              } finally {
                  mainLock.unlock();
              }
          }
          
     				 void interruptIfStarted() {
                      Thread t;
						( state=-1 表示任务还处于初始化节点,没有运行,无需中断 )  
        // 只有  State >= 0 才会中断            线程不是null                 线程没有被中断
             if (getState() >= 0         && (t = thread) != null     && !t.isInterrupted()) {
                          try {
                              t.interrupt(); // 线程开始被中断
                          } catch (SecurityException ignore) {
                          }
                      }
                  }
tryTerminate

image-20231203204624180

/*
   如果(关闭且池和队列为空)或(停止且池为空),则转换为 TERMINATED 状态。
   如果符合终止条件但workerCount不为零,则中断空闲工作线程以确保关闭信号传播。
   必须在任何可能导致终止的操作之后调用此方法 - 减少工作线程数或在关闭期间从队列中删除任务。
   该方法是非私有的,允许从 ScheduledThreadPoolExecutor 进行访问
 */
final void tryTerminate() {
    for (;;) {
        int c = ctl.get();
// 线程池是运行状态  || 运行状态 > TIDYING(已经是 TERMINATED)|| 运行状态= SHUTDOWN 并且 工作队列是非空的 ==> 都直接return  不去尝试暂停线程池
        if (isRunning(c) || runStateAtLeast(c, TIDYING) || (runStateOf(c) == SHUTDOWN && !workQueue.isEmpty()))
            return;
      
      /*
      何时结束线程池
      1、线程池的 状态是  STOP
      2、线程池 是 SHUTDOWN 且 阻塞队列是空的
      */ 
        if (workerCountOf(c) != 0) { // 判断一下线程池工作线程数量 是不是 0 
          // 线程池中的 工作线程数量 还是有的,中断一个的线程
            interruptIdleWorkers(ONLY_ONE);
            return;
        }
// 线程池工作线程数量 = 0  才能结束,且只有线程池中的最后一个线程才会走到这里
        final ReentrantLock mainLock = this.mainLock;
        mainLock.lock();
        try {
            if (ctl.compareAndSet(c, ctlOf(TIDYING, 0))) {  //有一个线程 将 ctl 的值变为   TIDYING  中间状态
                try {
                    terminated();
                } finally {
                    ctl.set(ctlOf(TERMINATED, 0));   //finally 中就肯定 也会有一个线程 将 ctl 的值变为  TERMINATED 最终状态
                  // 唤醒条件队列中的线程,即唤醒所有等待终止的线程
                    termination.signalAll();  //调用处: 
                 
                }
                return;
            }
        } finally {
            mainLock.unlock();
        }
        // else retry on failed CAS
    }
}


    /**
     *中断可能正在等待任务的线程(如未锁定所示),以便它们可以检查终止或配置更改。
     */
    private void interruptIdleWorkers(boolean onlyOne) {
        final ReentrantLock mainLock = this.mainLock;
        mainLock.lock();
        try {
            for (Worker w : workers) {
                Thread t = w.thread;
                if (!t.isInterrupted() && w.tryLock()) {
                    try {
                        t.interrupt();
                    } catch (SecurityException ignore) {
                    } finally {
                        w.unlock();
                    }
                }
                if (onlyOne)
                    break;
            }
        } finally {
            mainLock.unlock();
        }
    }
awaitTermination

等待线程池中所有任务完成并终止。

image-20231203204818461

public boolean awaitTermination(long timeout, TimeUnit unit) throws InterruptedException {
              long nanos = unit.toNanos(timeout);
   					  final ReentrantLock mainLock = this.mainLock;
              mainLock.lock();
              try {
                 for (;;) {
                      if (runStateAtLeast(ctl.get(), TERMINATED))
                            return true;
                      if (nanos <= 0)
                            return false;
                      nanos = termination.awaitNanos(nanos); // 阻塞
                 }
               } finally {
                     mainLock.unlock();
            }
     }

流程图

完整

  • 13
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值