JDK线程池源码分析

全是个人理解产物,仅供参考


简述:我们经常会在代码中用到线程池,但是对代码底层实现比较陌生,我根据源码以及自己的理解整理了一下,如果是仅作了解,看下面这段简介即可

线程池执行器类Executors,提供了一众工厂方法,用于创建不同类型的线程池,包括但不限于
A)newCachedThreadPool():允许空闲线程存在的线程池
B)newFixedThreadPool:会回收空闲线程池的线程池

实际上它们的底层都是ThreadPoolExecutor类的实例,该实例有几个比较关键的字段
A)AtomicInteger ctl:32位int类型值,前3位记录了线程池状态,后29位记录了线程池中的Worker数量(Worker是定义在ThreadPoolExecutor的内部类)
B)HashSet<Worker> workers:存放Worker的数据结构
C)RejectedExecutionHandler handler:任务提交失败处理器,用于在任务提交失败时做相应处理
D)ThreadFactory threadFactory:线程池工厂,创建线程时使用,如果想对线程做某些定制,可以实现自己的线程池工厂然后传入
E)int corePoolSize:最小Worker数量,即最小线程数量,当线程池拥有的Worker(线程)数量少于该值时,不清理空闲线程(当然前提是allowCoreThreadTimeOut为false的情况下)
F)boolean allowCoreThreadTimeOut:是否允许空闲线程过期回收,默认false,即线程空闲也不回收
G)long keepAliveTime:空闲线程过期时间

Worker类是ThreadPoolExecutor的内部类,该类继承了父类abstractQueuedSynchronizor,主要是为了继承执行任务时锁的相关操作。几个关键字段如下
A)Thread thread:持有的线程
B)firstTask:初始化Worker时携带的头任务,可以为空,该任务不需要加入任务队列进行排队
C)int state:父类的字段,用于记录Worker的状态,一般0代表空闲,1代表正在执行任务,还有一个特殊值-1,在构造函数中说明

Worker有且仅有一个构造函数干了三件事:
A)将Worker状态设置为了非法值-1,主要是为了避免Worker刚实例化就被中断线程,在开始执行第一个任务后,就会被置为正常值
B)赋予该Worker头任务
C)用线程池工厂threadFactory创建新线程

任务提交:当一个任务通过执行器Executorsexecute(Runnable command)方法提交时,会按以下步骤进行
A)首先会判断线程池状态,如果线程池Worker数量未达上限,直接创建一个新线程执行任务
B)如果达上限,则将新丢到任务队列
C)如果连任务队列都满了,会拒绝该任务的提交,并执行“任务提交失败处理器”——handlervoid rejectedExecution(Runnable r, ThreadPoolExecutor executor);的方法,该方法默认抛出一个异常

线程池拥有5种状态:
A)初始状态(RUNNING):线程池刚创建时,为RUNNING状态,既可以接受任务,也能执行任务
B)关闭线程池(to SHUTDOWN):当我们不想让线程池接受新任务,但是又想把已经接受的任务处理掉,就可以调用void shutdown()方法,关闭线程池,SHUTDOWN状态下,会继续执行已提交任务
C)关停线程池(to STOP)当我们不仅想让线程池不接受新任务,并且想让线程池停止正在执行的所有任务,可以在RUNNING和SHUTDOWN状态下执行List<Runnable> shutdownNow(),该方法除了会将线程池状态转变为STOP,还会返回所有未执行的任务
D)终止线程池(to TIDYING or TERMINATED):当线程池清理完所有任务(任务队列为空),不管是任务执行完毕,还是被迫放弃执行,任务池都会切换到TIDYING状态,然后再切换为TERMINATED状态

以下几点注意以下:
A)对于关键字段ctl的更改操作(即修改线程池状态和Worker数量),ThreadPoolExecutor大量使用了Lock锁和CAS思想来完成操作

B)线程池预留了许多钩子,支持面向切面编程,这些方法在ThreadPoolExecuter中默认为空,包括但不限于:

  • 执行任务run方法前的方法void beforeExecute()
  • 执行任务run方法后的方法void afterExecute()
  • 关闭任务池后的void onShutdown()
  • 终止任务池前的void terminated()

1.创建线程池

执行器类:java.util.concurrent.Executors,提供了一些类方法,使用工厂模式获得线程池

  • 动态线程池:需要的时候创建,池中最大线程数为int类型的最大值,线程空闲存活时间为60秒,过期则进行回收
public static ExecutorService newCachedThreadPool() {
    return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
                                  60L, TimeUnit.SECONDS,
                                  new SynchronousQueue<Runnable>());
}
  • 预分配线程池:线程池创建固定数量的线程
public static ExecutorService newFixedThreadPool(int nThreads) {
    return new ThreadPoolExecutor(nThreads, nThreads,
                                  0L, TimeUnit.MILLISECONDS,
                                  new LinkedBlockingQueue<Runnable>());
}
  • 预先分配单线程池:就像是线程数为1的FixedThreadPool。如果向其提交了多任务,那么这些任务将会排队,所有的任务都会使用相同的线程,按照它们被提交的顺序进行执行,SingleThreadExecutor会序列化所有提交给它的任务,并会维护自己(隐藏)的悬挂任务队列
public static ExecutorService newSingleThreadExecutor() {
    return new FinalizableDelegatedExecutorService
        (new ThreadPoolExecutor(1, 1,
                                0L, TimeUnit.MILLISECONDS,
                                new LinkedBlockingQueue<Runnable>()));
}

观察上面可以发现,实际上都使用了类ThreadPoolExecutor的构造器

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

对于方法说明如下

原文:
* Creates a new {@code ThreadPoolExecutor} with the given initial
* parameters and default thread factory and rejected execution handler.
* 通过给定的参数,并使用默认的“线程工厂”以及“任务提交失败处理器”,创建一个新的线程池

* It may be more convenient to use one of the {@link Executors} factory
* methods instead of this general purpose constructor.
* 比起直接使用该构造器,更建议使用类执行器类Executors的工厂方法来达到创建线程池的目的

对于几个入参,JDK说明如下

参数类型含义原文翻译
corePoolSizeint核心线程数the number of threads to keep in the pool, even if they are idle, unless {@code allowCoreThreadTimeOut} is set当线程池线程数量小于核心线程数,线程即使空闲,也不会被销毁,除非设置了“allowCoreThreadTimeOut”,即“允许核心线程超时被回收”
maximumPoolSizeint最大线程数量the maximum number of threads to allow in the pool线程池允许存在的最大线程数量
keepAliveTimelong空闲线程最大存活时间(数值)when the number of threads is greater than the core, this is the maximum time that excess idle threads will wait for new tasks before terminating当前线程数超过了核心线程数,如果此时存在空闲线程,将会被回收,回收标准即线程空闲时间超过该值
unitTimeUnit空闲线程最大存活时间(单位)the time unit for the {@code keepAliveTime} argumentkeepAliveTime参数的单位
workQueueBlockingQueue workQueue线程组织形式the queue to use for holding tasks before they are executed. This queue will hold only the {@code Runnable} tasks submitted by the {@code execute} method存储待执行的任务的数据结构

当参数不合理时,会抛出异常,如下

异常抛出原因含义
IllegalArgumentExceptioncorePoolSize < 0最大空闲线程数小于0
IllegalArgumentExceptionkeepAliveTime < 0空闲线程最大存活时间小于0
IllegalArgumentExceptionmaximumPoolSize <= 0最大线程数小于等于0
IllegalArgumentExceptionmaximumPoolSize<corePoolSize最大线程数小于允许最大空闲线程数
NullPointerExceptionworkQueue is nullworkQueue为null

实际上这个构造器方法调用的是另一个构造器

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();
	...
}

比起上一个构造器方法,这个方法多了两个参数,JDK说明如下

参数类型含义原文翻译
threadFactoryThreadFactory线程工类he factory to use when the executor creates a new thread创建线程的工厂。我想之所以可以指定线程工厂,主要是可能根据业务需求,需要对创建的线程设置相关属性,比如线程优先级、守护线程等
handlerRejectedExecutionHandler处理器the handler to use when execution is blocked because the thread bounds and queue capacities are reached任务提交到任务池失败时,调用该处理器。线程数量达上限且任务队列已满,会导致提交任务会失败,还有一种情况,此处没说明,即线程池处于非RUNNING状态,也会导致任务提交失败,想在该情况做某些处理时,可以通过该参数达到目的

2.提交任务

public Future<?> submit(Runnable task)方法为例,当我们提交一个任务时,调用Executorspublic Future<?> submit(Runnable task)方法

类:Executors
public Future<?> submit(Runnable task) {
    return e.submit(task);
}

此时e是ExecutorService变量,实际上引用的是ThreadPoolExecutor的实例

而类ThreadPoolExecutor并没有重写public Future<?> submit(Runnable task)方法,它继承了父类AbstractExecutorService的方法

类:AbstractExecutorService
public Future<?> submit(Runnable task) {
    if (task == null) throw new NullPointerException();
    RunnableFuture<Void> ftask = newTaskFor(task, null);
    execute(ftask);
    return ftask;
}

该方法分为四步

  • 第一步:判空if (task == null) throw new NullPointerException();
  • 第二步:创建任务RunnableFuture<Void> ftask = newTaskFor(task, null);
类:AbstractExecutorService
protected <T> RunnableFuture<T> newTaskFor(Runnable runnable, T value) {
    return new FutureTask<T>(runnable, value);
}

类:FutureTask
public FutureTask(Runnable runnable, V result) {
    this.callable = Executors.callable(runnable, result);
    this.state = NEW;       // ensure visibility of callable
}

类:Executors
public static <T> Callable<T> callable(Runnable task, T result) {
    if (task == null)
        throw new NullPointerException();
    return new RunnableAdapter<T>(task, result);
}

类:Executors的静态内部类RunnableAdapter
static final class RunnableAdapter<T> implements Callable<T> {
    final Runnable task;
    final T result;
    RunnableAdapter(Runnable task, T result) {
        this.task = task;
        this.result = result;
    }
    public T call() {
        task.run();
        return result;
    }
}
  • 第三步:执行任务execute(ftask);详见4.执行任务

  • 第四步:返回结果return ftask;


3.Worker——任务及线程持有者

类说明

* Class Worker mainly maintains interrupt control state for
* threads running tasks, along with other minor bookkeeping.
* This class opportunistically extends AbstractQueuedSynchronizer
* to simplify acquiring and releasing a lock surrounding each
* task execution.  This protects against interrupts that are
* intended to wake up a worker thread waiting for a task from
* instead interrupting a task being run.  We implement a simple
* non-reentrant mutual exclusion lock rather than use
* ReentrantLock because we do not want worker tasks to be able to
* reacquire the lock when they invoke pool control methods like
* setCorePoolSize.  Additionally, to suppress interrupts until
* the thread actually starts running tasks, we initialize lock
* state to a negative value, and clear it upon start (in
* runWorker). 
* Worker类实例包含几个重要参数,包括用
* A)是否正在执行任务的标志位(state,该字段存在于父类AbstractQueuedSynchronizer中)
* B)执行任务的线程(thread)
* C)该Worker的初始任务(firstTask,该变量可以为空,此时该Worker创建主要是为了执行任务队列中的任务)
* 该类继承了类AbstractQueuedSynchronizer,主要是为了简化锁的获取操作(该锁主要是针对线程执行任务进行上锁)
* Worker的初始状态被设置为非法值(-1),主要是为了避免线程刚初始化完毕,还未执行任务就被中断,
* 这个非法值将会在线程正式执行任务的前一刻进行清除
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. 
    * Worker初始化时携带的初始任务,可以为空
    Runnable firstTask;
    
    * Per-thread task counter
    * Worker完成任务数
    volatile long completedTasks;

    * Creates with given first task and thread from ThreadFactory.
    * @param firstTask the first task (null if none)
    * Worker类就这么一个构造器,且只有一处调用,即线程池添加Worker时,干了三件事
    * 设置Worker状态为-1
    * 设置头任务
    * 使用线程工厂创建新线程并赋予变量thread
    Worker(Runnable firstTask) {
        setState(-1); // inhibit interrupts until runWorker
        this.firstTask = firstTask;
        this.thread = getThreadFactory().newThread(this);
    }

    * 实现Runnable接口重写的run方法,不用解释了吧?
    public void run() {
        runWorker(this);
    }

    // Lock methods
    // The value 0 represents the unlocked state.
    // The value 1 represents the locked state.
	*这一部分实际上是实现了自己一个变种的ReentaintLock锁

	* 判断该Worker锁是否已经被持有,不对外开放
    protected boolean isHeldExclusively() {
        return getState() != 0;
    }

	* 通过CAS获取该Worker锁,不对外开放
    protected boolean tryAcquire(int unused) {
        if (compareAndSetState(0, 1)) {
            setExclusiveOwnerThread(Thread.currentThread());
            return true;
        }
        return false;
    }

	* 释放Worker锁,不对外开放
    protected boolean tryRelease(int unused) {
        setExclusiveOwnerThread(null);
        setState(0);
        return true;
    }

    public void lock()        { acquire(1); }
    
	* 通过CAS获取该Worker锁,对protected方法的简单封装
    public boolean tryLock()  { return tryAcquire(1); }
    
    * 释放Worker锁,对protected方法的简单封装
    public void unlock()      { release(1); }
    
	* 判断该Worker锁是否已经被持有,对protected方法的简单封装
    public boolean isLocked() { return isHeldExclusively(); }

    void interruptIfStarted() {
        Thread t;
        if (getState() >= 0 &&    初始化状态,不允许中断线程
        	(t = thread) != null &&    Worker没有可执行任务的线程,无法中断
        	!t.isInterrupted()) {    线程本身就是中断状态,无需再中断
	            try {
	                t.interrupt();
	            } catch (SecurityException ignore) {
            }
        }
    }
}

注:通过对Worker类的分析,可以得知,除非线程池工厂创建线程失败,一般情况下,“线程池Worker数量”即“线程池线程数量”,后续描述中,可将两者等同


4.执行任务——public void execute(Runnable command)

方法说明

* Executes the given task sometime in the future.  The task
* may execute in a new thread or in an existing pooled thread.
* 在将来的某个时刻执行给定的任务,该任务可能由一个新线程中执行,或者
* 由已经在线程池中的线程执行在已经存在的线程中执行

* If the task cannot be submitted for execution, either because this
* executor has been shutdown or because its capacity has been reached,
* the task is handled by the current {@code RejectedExecutionHandler}.
* 如果任务无法被提交或者执行,无论是因为线程池已经关闭(非RUNNING态),或者线程数量
* 达到上限,任务都将会由 RejectedExecutionHandler 进行处理
* 
* @param command the task to execute
* 待执行的任务

源码解读

* Proceed in 3 steps:
* 分三步走

* 1. If fewer than corePoolSize threads are running, try to
* start a new thread with the given command as its first
* task.  The call to addWorker atomically checks runState and
* workerCount, and so prevents false alarms that would add
* threads when it shouldn't, by returning false.
* 如果现有的Worker数量少于“核心线程数”,则尝试创建一个新Worker,
* 并将该任务作为初始任务。当创建新Worker失败时,会返回false
* (Workder的创建会通过原子性的方式去检查线程池状态和线程池现有
* Worker数量,避免在线程池不允许的情况下添加Worker)

* 2. If a task can be successfully queued, then we still need
* to double-check whether we should have added a thread
* (because existing ones died since last checking) or that
* the pool shut down since entry into this method. So we
* recheck state and if necessary roll back the enqueuing if
* stopped, or start a new thread if there are none.
* 如果一个任务成功加入任务队列,我们仍然需要重复验证我们是否需要添加
* 新Worker(因为可能在将任务加入任务队列过程中,有Worker被回收了),
* 或者当我们判定线程池还在运行,然后执行下一步的过程中,线程池刚好关闭。
* 所以我们必须重新检查线程池状态,如果线程池状态不允许再提交任
* 务(非RUNNING状态),我们还需要将刚添加的任务从任务队列移除(即回滚),
* 如果此时任务添加到任务队列成功,但是线程池已经没有Worker,我们需要
* 添加一个没有初始任务的Worker来执行刚提交到任务队列的任务

* 3. If we cannot queue task, then we try to add a new
* thread.  If it fails, we know we are shut down or saturated
* and so reject the task.
* 如果提交任务到任务队列失败,此时我们可以尝试新起一个Worker,
* 将该任务作为它的初始任务,如果仍然提交任务失败,说明线程池已
* 经无法再接受更多任务(所有Worker都在执行任务+任务队列已满)
类:ThreadPoolExecutor
private final AtomicInteger ctl = new AtomicInteger(ctlOf(RUNNING, 0))    详见4.1 AtomicInteger类型字段ctl)
private final BlockingQueue<Runnable> workQueue;    详见4.2 任务队列workQueue

public void execute(Runnable command) {
    if (command == null)
        throw new NullPointerException();
    int c = ctl.get();    获取关键参数,该参数记录了现有的Worker数量,以及线程池状态
    if (workerCountOf(c) < corePoolSize) {    当现有Worker数量,少于核心线程数
        if (addWorker(command, true))    添加Worker,详见4.3 添加Worker
            return;
        c = ctl.get();    添加失败,考虑可能是线程池发生了改变(Worker数量 或 线程池状态),所以重新获取关键参数
    }
   
如果代码执行到这里,代表添加Worker失败了,原因很多,比如
A)Worker数量已达上限(此时以核心线程数为上限)
B)其他(原因见4.3 添加Worker)

    if (isRunning(c) && workQueue.offer(command)) {    当线程池是否处于RUNNING状态(此时可以往线程池塞任务),且任务添加到任务队列成功
        int recheck = ctl.get();    此刻再次获取关键参数(怕其他线程改变了线程池)
        if (! isRunning(recheck) && remove(command))    如果此时线程池已经非RUNNING状态,且从任务队列中移除任务(详见4.4 从任务队列移除任务)
            reject(command);    详见4.5 任务提交失败处理
        else if (workerCountOf(recheck) == 0)    如果此时线程池的Worker数量为0,则添加一个没有头任务的Worker(毕竟我们刚往任务队列丢了一个任务,却没有能执行任务的Worker,这时候就需要创建一个)
            addWorker(null, false);
    }

如果代码执行到这里,代表
A)执行任务的Worker已经达到上限(核心线程数)
B)添加进任务队列也失败了(比如任务队列已满)
此时会做最后的挣扎————将Worker上限切换为“最大线程数”,将任务作为该Worker的初始任务去执行,如果也失败了,代表
C)执行任务的Worker已经达到上限(最大线程数)
放弃提交任务,执行“任务提交失败处理器”

    else if (!addWorker(command, false))
        reject(command);

	分析一:只有当线程池处于RUNNING状态时,才会接受新任务,在添加Worker的尝试已经失败的前提下,
	      只能将任务塞进任务队列,当添加任务到任务队列成功时,需要检查两件事
	A)线程池状态还在RUNNING,如果不满足,说明已经不接受新任务,此时应该把任务从任务队列移出
	  - 如果移出成功,说明任务提交失败了,就可以执行“任务提交失败处理器”
	  - 如果移出失败(极大可能是被其他Worker取走了),虽然逻辑上不允许
	    添加任务了,但是任务移出失败,实际上是变相的任务提交成功
	B)如果线程池的Worker数量为0,此时任务队列仍然有任务等待执行,就需要再添加一个新Worker
	  来执行任务队列中待执行的任务(此时起码有一个待执行任务,即本次添加的任务)

	分析二:如果添加任务失败了,存在两种可能
	A)线程池已经处于非RUNNING状态了,此时创建一个带有初始任务的Worker
	  肯定会失败(见4.3 添加Worker),执行“任务提交失败处理器”
	B)任务提交到任务队列失败,此时创建一个带有初始任务的Worker
	  (此处Worker上限已经从“核心线程数”切换为“最大线程数”),
	  还是存在两种可能
	  - 添加成功,执行任务
	  - 添加失败,执行“任务提交失败处理器”
}

总结:
经过上面的分析,可以得出任务提交到线程池中的优先级顺序如下(从高到低)
A)优先创建一个新Worker来执行,此时以“核心线程数”为上限(即提交到绿色区域)
B)如果Worker数量已经达到了上限(核心线程数),将任务丢入任务队列(即提交到橙色区域)
C)如果连任务队列都满了,就只能再尝试创建Worker去执行任务,不过此时以“最大线程数”为上限(即提交到蓝色区域)
在这里插入图片描述


4.1 任务队列workQueue——管理“待执行任务”的数据结构
类:ThreadPoolExecutor
private final BlockingQueue<Runnable> workQueue;

在线程池执行器构造线程池时,一般使用的是工厂方法模式,实际上,工厂方法中,已经将这个变量的引用对象传入了,比如

①动态线程池newCachedThreadPool:传入的是new SynchronousQueue<Runnable>()
②预先分配线程池newFixedThreadPool:传入的是new LinkedBlockingQueue<Runnable>()

我们先分析new SynchronousQueue<Runnable>()

private transient volatile Transferer<E> transferer;

* Creates a {@code SynchronousQueue} with nonfair access policy.
* 用非公平策略创建一个同步队列
public SynchronousQueue() {
    this(false);
}

public SynchronousQueue(boolean fair) {
    transferer = fair ? new TransferQueue<E>() : new TransferStack<E>();
}

实际上是创建的是new TransferStack<E>()这么一个数据结构

数据结构这边后面再补充


4.2 AtomicInteger类型字段ctl——记录“线程池状态”和“Worker数量”
类:ThreadPoolExecutor
private final AtomicInteger ctl = new AtomicInteger(ctlOf(RUNNING, 0))

private static int ctlOf(int rs, int wc) { return rs | wc; }
wc为0,任何数对0|的位运算,等于本身,也就是实际上,ctlOf(RUNNING, 0)的值实际上等于RUNNING本身,即

private final AtomicInteger ctl = new AtomicInteger(RUNNING)

private static final int COUNT_BITS = Integer.SIZE - 3;32-3=29

线程池的五种状态
private static final int RUNNING    = -1 << COUNT_BITS;
private static final int SHUTDOWN   =  0 << COUNT_BITS;
private static final int STOP       =  1 << COUNT_BITS;
private static final int TIDYING    =  2 << COUNT_BITS;
private static final int TERMINATED =  3 << COUNT_BITS;
-1表示为0b 1111 1111 1111 1111 1111 1111 1111 1111,左移29位,即0b 1110 0000 0000 0000 0000 0000 0000 0000
 0表示为0b 0000 0000 0000 0000 0000 0000 0000 0000,左移29位,即0b 0000 0000 0000 0000 0000 0000 0000 0000
 1表示为0b 0000 0000 0000 0000 0000 0000 0000 0001,左移29位,即0b 0010 0000 0000 0000 0000 0000 0000 0000
 2表示为0b 0000 0000 0000 0000 0000 0000 0000 0010,左移29位,即0b 0100 0000 0000 0000 0000 0000 0000 0000
 3表示为0b 0000 0000 0000 0000 0000 0000 0000 0011,左移29位,即0b 0110 0000 0000 0000 0000 0000 0000 0000

得出值ctl的初始值的二进制表示为0b 1110 0000 0000 0000 0000 0000 0000 0000,其中包含了两个信息,分别是

  • ①线程池状态(前3位)
  • ②线程池Worker数量(后29位)

方法private static int workerCountOf(int c) { return c & CAPACITY; },使用线程池线程数量掩码,从信息字段ctl中获取线程池中的Worker数量

类:ThreadPoolExecutor
private static final int CAPACITY   = (1 << COUNT_BITS) - 1;
1左移29位,即0b 0010 0000 0000 0000 0000 0000 0000 0000
-1后,即0b 0001 1111 1111 1111 1111 1111 1111 1111

private static int workerCountOf(int c)  { return c & CAPACITY; }
     1110 0000 0000 0000 0000 0000 0000 0000
&    0001 1111 1111 1111 1111 1111 1111 1111
————————————————————————————————————————————
     0000 0000 0000 0000 0000 0000 0000 0000

方法private static int runStateOf(int c) { return c & ~CAPACITY; },使用线程池状态掩码,从信息字段ctl中获取线程池状态

 CAPACITY为0b 0001 1111 1111 1111 1111 1111 1111 1111
~CAPACITY即0b 1110 0000 0000 0000 0000 0000 0000 0000

private static int runStateOf(int c)     { return c & ~CAPACITY; }
     1110 0000 0000 0000 0000 0000 0000 0000
&    1110 0000 0000 0000 0000 0000 0000 0000
————————————————————————————————————————————
     1110 0000 0000 0000 0000 0000 0000 0000

4.3 添加Worker——addWorker(command, true)

方法说明

* Checks if a new worker can be added with respect to current
* pool state and the given bound (either core or maximum). If so,
* the worker count is adjusted accordingly, and, if possible, a
* new worker is created and started, running firstTask as its
* first task. This method returns false if the pool is stopped or
* eligible to shut down. It also returns false if the thread
* factory fails to create a thread when asked.  If the thread
* creation fails, either due to the thread factory returning
* null, or due to an exception (typically OutOfMemoryError in
* Thread.start()), we roll back cleanly.

* 首先对线程池的状态,以及线程池workder上限(“核心线程数”或“最大
* 线程数”)进行检查,如果目前线程池允许创建新workder,则对记录workder
* 数量的字段进行相应调整。如果条件允许,此时一个新的workder被创建,
* 并且将firstTask作为它的第一个任务开始工作。该方法将会在以下情况返回false
A)当线程池关停(STOP),或者线程池关闭(SHUTDOWN)
B)当线程工厂接受创建线程的请求,并创建失败时,无论是因为线程工厂创建线程后
返回null,还是因为异常(最典型的就是OOM异常),都会进行回滚

参数说明

  • firstTask(Runnable)
* @param firstTask the task the new thread should run first (or
* null if none). Workers are created with an initial first task
* (in method execute()) to bypass queuing when there are fewer
* than corePoolSize threads (in which case we always start one),
* or when the queue is full (in which case we must bypass queue).
* Initially idle threads are usually created via
* prestartCoreThread or to replace other dying workers.

* 这是新创建的Worker的初始化任务,需要第一个被执行(可以为空),Workder将会在以
* 下情况时创建,并携带初始任务(在方法execute()中提交的那个任务),
* 这个任务可以跳过排队,直接执行。
A)当前线程数量少于corePoolSize(核心线程数),此时,优先创建一个新Worker执行刚提交的任务
B)满足A的前提下,且任务队列已满时,将刚提交的任务塞入新线程执行(此时以最大线程数为上限)
* 初始化空闲Worker一般在两种情况下进行
A)调用prestartCoreThread方法预分配线程时
B)有旧线程死亡,初始化新的空闲线程进行替代
  • core(boolean)
* @param core if true use corePoolSize as bound, else
* maximumPoolSize. (A boolean indicator is used here rather than a
* value to ensure reads of fresh values after checking other pool
* state).
* @return true if successful

* 当该值为true时,使用corePoolSize(核心线程数)作为线程上限,
* 当该值为false时,使用maximumPoolSize(最大线程数)作为线程上限。

源码解读

  • 第一部分:对线程池状态和线程池线程数量做修改
private boolean addWorker(Runnable firstTask, boolean core) {
	retry:
	for (;;) {
	    int c = ctl.get();    获取线程池状态和线程池Worker数量记录字段
	    int rs = runStateOf(c);    通过掩码,获取线程池状态
	    
	
	    // Check if queue empty only if necessary.
	    if (rs >= SHUTDOWN &&
	        ! (rs == SHUTDOWN &&
	        firstTask == null &&
	        ! workQueue.isEmpty()))
	        return false;
	        
	    * 分析一:因为只有RUNNING、SHUTDOWN状态下,允许执行任务(详见6 线程池状态),
	    * STOP、TIDYING、TERMINATED状态下是不执行任务的,添加Worker没有意义,所以以下情况,拒绝添加Worker
	    * A)线程池处于非RUNNING、SHUTDOWN状态时
	    * 分析二:SHUTDOWN状态下,虽然此时已经不允许提交新任务,但是任务队列中可能
	    * 存在待执行的任务,且恰好此时线程池Worker数为0,此时只能创建一个新Worker
	    * 来执行任务队列中的任务,很明显,这种情况下创建的Worker,是不携带初始任务
	    * 的,毕竟它的创建目的是为了执行任务队列中的任务,而非新提交的任务
	    * B)线程池处于SHUTDOWN状态,添加Worker时,携带初始任务(只有在提交新任务的情况下,创建Worker会携带初始任务,而SHUTDOWN状态明显是不能提交任务的)
	    * C)线程池处于SHUTDOWN状态,添加Worker时,虽然未携带初始任务,但是任务队列已经空了(因为处于SHUTDOWN状态,不允许提交新任务,任务队列只增不减,当任务队列为空,再添加新Worker也不会有任务给该Worker执行)
	       
	    for (;;) {
	        int wc = workerCountOf(c);    获取Worker数量
	        if (wc >= CAPACITY ||    当Worker数大于线程池最大线程容量或边界值,Worker添加失败
	            wc >= (core ? corePoolSize : maximumPoolSize))    根据业务需求不同,边界值会是在“最大空闲线程数”或“最大线程数”中的一个
	            return false;
	        if (compareAndIncrementWorkerCount(c))    通过原子类AtomicInteger的CAS思想的方法,使记录Worker数量的字段+1,跳出循环
	            break retry;
	        c = ctl.get();    CAS修改线程池Worker数量失败,说明该值被其他线程修改过(要么是修改过Worker数量,要么是修改线程池状态),需要重新获取该参数
	        if (runStateOf(c) != rs)    线程池状态被修改,则回到第一次循环吗,重新做线程池状态相关的判断
	            continue retry;
	        // else CAS failed due to workerCount change; retry inner loop
	        仅仅是Worker数量被修改,则重新执行第二层循环即可
	    }
	}
	......
}
  • 第二部分:添加Worker
private boolean addWorker(Runnable firstTask, boolean core) {
	private final ReentrantLock mainLock = new ReentrantLock();
	private final HashSet<Worker> workers = new HashSet<Worker>();
	private int largestPoolSize;    我个人认为这应该是个记录字段,记录了这个线程池拥有过的Worker上限
	......
	boolean workerStarted = false;
	boolean workerAdded = false;
	Worker w = null;
	try {
	    w = new Worker(firstTask);    创建新Worker,详见下方
	    final Thread t = w.thread;
	    if (t != null) {    如果线程为空(无论是因为创建线程失败,还是遭遇异常),直接返回false
	        final ReentrantLock mainLock = this.mainLock;	这个是final类型的实例字段,获取锁对象
	        mainLock.lock();	上锁,划分临界区
	        try {
	            // Recheck while holding lock.
	            // Back out on ThreadFactory failure or if
	            // shut down before lock acquired.
	            int rs = runStateOf(ctl.get());    获取线程池状态
	
				分析:两种情况下是合法的
				A)线程池处于RUNNING状态
				B)线程池处于SHUTDOWN状态,但是创建Worker时没有携带初始
				  化任务(代表这个Worker的创建是为了执行任务队列中的任务)
	            if (rs < SHUTDOWN ||
	                (rs == SHUTDOWN && firstTask == null)) {
	                if (t.isAlive()) //precheck that t is startable	
	                    throw new IllegalThreadStateException();    线程刚创建,理论上应该等待任务的到来,此时应该是NEW状态
	                workers.add(w);    将新Workder加入维护Worker的集合中
	                int s = workers.size();
	                if (s > largestPoolSize)	largestPoolSize这个字段,我未找到相关初始化代码,作为实例变量,在对象创建时,拥有的默认值应该是0
	                    largestPoolSize = s;    当现有Worker数量大于历史值时,更新该字段
	                workerAdded = true;
	            } 
	        } finally {
	            mainLock.unlock();
	        }
	        if (workerAdded) {
	            t.start();
	            workerStarted = true;
	        }
	    }
	} finally {
	    if (! workerStarted)
	        addWorkerFailed(w);    当任务启动失败,需要做一些善后处理,见下方
	}
	return workerStarted;
}

-------------分界线,最近完善到此处--------------------

  • 添加Worker失败后的善后处理
类:ThreadPoolExecutor
private void addWorkerFailed(Worker w) {
    final ReentrantLock mainLock = this.mainLock;
    mainLock.lock();
    try {
        if (w != null)
            workers.remove(w);    从Workder集中将Worker移除
        decrementWorkerCount();    通过原子类AtomicInteger的CAS思想的方法,使使记录Worker数量的字段-1
        tryTerminate();    尝试将线程池状态置为TERMINATED
    } finally {
        mainLock.unlock();
    }
}

4.4 从任务队列移除任务——public boolean remove(Runnable task)

方法说明

* Removes this task from the executor's internal queue if it is
* present, thus causing it not to be run if it has not already
* started.
* 如果该任务已经在任务队列中,则从任务队列中,将该任务移除,即便该
* 任务还没被执行过

* <p>This method may be useful as one part of a cancellation
* scheme.  It may fail to remove tasks that have been converted
* into other forms before being placed on the internal queue. For
* example, a task entered using {@code submit} might be
* converted into a form that maintains {@code Future} status.
* However, in such cases, method {@link #purge} may be used to
* remove those Futures that have been cancelled.
* 该方法作为取消计划任务的一部分时将极为有用
* 但是该方法可能会执行失败,比如任务已经被执行,并且已经将返回值加入返回值集时,
* 但是,这种情况下,这个方法也可能被用于移除该任务的返回值(这段翻译不一定准确,待考究)

* @param task the task to remove
* @return {@code true} if the task was removed

源码解读

public boolean remove(Runnable task) {
    boolean removed = workQueue.remove(task);
    tryTerminate(); // In case SHUTDOWN and now empty   详见4.6 线程池状态
    return removed;
}

4.5 任务提交失败处理——void rejectedExecution(Runnable r, ThreadPoolExecutor executor);

方法说明

* Invokes the rejected execution handler for the given command.
* Package-protected for use by ScheduledThreadPoolExecutor.
* 调用任务提交失败处理器

源码解读

类:ThreadPoolExecutor
private volatile RejectedExecutionHandler handler;   任务提交失败处理器

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

可以看到使用调用的是处理器的方法void rejectedExecution(Runnable r, ThreadPoolExecutor executor);

通过执行器Executors的工厂方法创建的线程池,使用的一般都是默认的 ” 任务提交失败处理器 “

类:ThreadPoolExecutor
private static final RejectedExecutionHandler defaultHandler = new AbortPolicy();

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

类:AbortPolicy
public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
    throw new RejectedExecutionException("Task " + r.toString() +
                                         " rejected from " +
                                         e.toString());
}

实际上就是抛出了一个任务提交失败的异常说明而已,我们当然可以实现自己的 “ 任务提交异常处理器 ” ,去完成我们想要的逻辑


5 真正执行任务的方法——void run()

类:ThreadPoolExecutor
public void run() {
    runWorker(this);
}

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();
            // If pool is stopping, ensure thread is interrupted;
            // if not, ensure thread is not interrupted.  This
            // requires a recheck in second case to deal with
            // shutdownNow race while clearing interrupt
            if ((runStateAtLeast(ctl.get(), STOP) ||
                 (Thread.interrupted() &&
                  runStateAtLeast(ctl.get(), STOP))) &&
                !wt.isInterrupted())
                wt.interrupt();    当线程池处于STOP状态时,中断当前线程
            try {
                beforeExecute(wt, task);    钩子,面向切面编程,如果想在执行任务前做什么操作,可以重写该方法,默认为空
                Throwable thrown = null;
                try {
                    task.run();    执行任务
                } catch (RuntimeException x) {
                    thrown = x; throw x;
                } catch (Error x) {
                    thrown = x; throw x;
                } catch (Throwable x) {
                    thrown = x; throw new Error(x);
                } finally {
                    afterExecute(task, thrown);    钩子,面向切面编程,如果想在执行任务后做什么操作,可以重写该方法,默认为空
                }
            } finally {
                task = null;
                w.completedTasks++;    完成任务数+1
                w.unlock();
            }
        }
        completedAbruptly = false;
    } finally {
        processWorkerExit(w, completedAbruptly);    善后处理,见5.1 Worker善后处理
    }
}

5.1 Worker善后处理
private void processWorkerExit(Worker w, boolean completedAbruptly) {
    if (completedAbruptly) 如果worker中线程是被突然打断的,比如线程池状态切换为STOP时,直接减去一个Worker数量
        decrementWorkerCount();

    final ReentrantLock mainLock = this.mainLock;
    mainLock.lock();
    try {
        completedTaskCount += w.completedTasks;
        workers.remove(w);   从Worker集中移除该Worker
    } finally {
        mainLock.unlock();
    }

    tryTerminate();

    int c = ctl.get();
    if (runStateLessThan(c, STOP)) {    当线程池处于RUNNING或SHUTDOWN状态时
        if (!completedAbruptly) {    Worker是自动停止工作,而非被强制停止
            int min = allowCoreThreadTimeOut ? 0 : corePoolSize;    判断是否允许空闲线程的存在
            if (min == 0 && ! workQueue.isEmpty())    不允许空闲线程存在,但是任务队列又有任务时
                min = 1;   允许起码一条空闲线程的存在(实际上这个空闲线程立马要执行任务队列中的任务)
            if (workerCountOf(c) >= min)    当Worker数量大于等于限定值,直接返回
                return; // replacement not needed
        }
在线程池允许添加Worker的情况下(RUNNING或SHUTDOWN状态)以下两种情况添加Worker
A)Worker进行善后工作是因为没任务执行了,而非被突然打断
B)Worker进行善后工作虽然是因为被突然打断,但是此时发现该线程池Worker数量仍然不饱和
        addWorker(null, false);    
    }
}

6 线程池状态

线程池一共有五种状态

线程池状态代表值接受任务执行任务备注
RUNNING-1✔️✔️线程池刚创建时的状态
SHUTDOWN0✖️✔️线程池关闭,清理所有空闲线程,不再接受新任务,但是会执行已经提交的任务
STOP1✖️✖️线程池关停,不再接受新任务,也不再执行任务,执行中的任务会被中断
TIDYING2✖️✖️确认已经没有任务在执行,Worker数量为0,才能从SHUTDOWN或STOP状态转变为TIDYING
TERMINATED3✖️✖️线程池注销

线程池创建 ==> RUNNING

private final AtomicInteger ctl = new AtomicInteger(ctlOf(RUNNING, 0));
前面分析过
ctl=new AtomicInteger(RUNNING)

RUNNING ===> SHUTDOWN

类:ThreadPoolExecutor
public void shutdown() {
   final ReentrantLock mainLock = this.mainLock;    获取实例锁
   mainLock.lock();    划分临界区
   try {
       checkShutdownAccess();    相关权限检查
       advanceRunState(SHUTDOWN);    通过CAS操作,更新线程池状态为SHUTDOWN
       interruptIdleWorkers();    中断所有空闲线程
       onShutdown(); /* hook for ScheduledThreadPoolExecutor */    如果有什么希望在线程池从RUNNING转变为SHUTDOWN时操作的,可以重写该方法,ThreadPoolExecutor该方法为空
   } finally {
       mainLock.unlock();
   }
   tryTerminate();
}

private void advanceRunState(int targetState) {
   for (;;) {
       int c = ctl.get();
       if (runStateAtLeast(c, targetState) ||
           ctl.compareAndSet(c, ctlOf(targetState, workerCountOf(c))))
           break;
   }
}

RUNNING,SHUTDOWN ===> STOP

public List<Runnable> shutdownNow() {
    List<Runnable> tasks;
    final ReentrantLock mainLock = this.mainLock;
    mainLock.lock();
    try {
        checkShutdownAccess();
        advanceRunState(STOP);   通过CAS操作将线程池状态修改为STOP
        interruptWorkers();    中断所有线程(除了刚初始化,状态为-1的线程外),无论是否在执行任务
        tasks = drainQueue();    将任务队列中所有待执行的任务倒出,准备返回
    } finally {
        mainLock.unlock();
    }
    tryTerminate();
    return tasks;
}

SHUTDOWN,STOP ===> TIDYING ===> TERMINATED

final void tryTerminate() {
    for (;;) {
        int c = ctl.get();
        if (isRunning(c) ||    RUNNING状态不允许切换为TIDYING
            runStateAtLeast(c, TIDYING) ||    线程池如果已经是TIDYING,说明try terminated请求已经被提交
            (runStateOf(c) == SHUTDOWN && ! workQueue.isEmpty()))    线程池在SHUTDOWN状态是可以继续执行任务的,如果此时任务队列还有任务,必须等待任务队列任务都执行完毕,才能关闭线程池
            return;
        if (workerCountOf(c) != 0) { /* Eligible to terminate */ 如果此时仍然有worker在工作,不允许切换为TERMINATED
            interruptIdleWorkers(ONLY_ONE);
            return;
        }

        final ReentrantLock mainLock = this.mainLock;
        mainLock.lock();
        try {
            if (ctl.compareAndSet(c, ctlOf(TIDYING, 0))) {    通过CAS操作将线程池状态切换为TIDYING
                try {
                    terminated();    如果有什么希望在线程池从TIDYING转变为TERMINATED时操作的,可以重写该方法,ThreadPoolExecutor该方法为空
                } finally {
                    ctl.set(ctlOf(TERMINATED, 0));
                    termination.signalAll();
                }
                return;
            }
        } finally {
            mainLock.unlock();
        }
        // else retry on failed CAS
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值