线程池ThreadPoolExecutor

 

一、线程的一些概念

进程:每个进程都有独立的代码和空间,例如QQ和WeChat
线程:程序执行运算的最小单位,在同一进程中共享资源
并发:在同一时刻,一个cpu只能执行一个线程,但是速度快,它可以快速的在线程间切换
并行:多个cpu同时执行一段代码,达到真正意义上的并行

二、线程池简介

定义:管理一组同构工作线程的资源池。
特性:重用线程。
意义:避免频繁的线程构建与销毁,提升运行速度。

三、基础属性

/**
* ctl低29位表示 workerCount :有效的线程数量;
* ctl高3位表示runState:运行状态,运行,关闭等
*/
// 初始化时有效的线程数为0, 此时ctl为: 1010 0000 0000 0000 0000 0000 0000 0000
private final AtomicInteger ctl = new AtomicInteger(ctlOf(RUNNING, 0));

// 高3位用来表示运行状态,此值用于运行状态向左移动的位数,即29位(Integer.SIZE=32)
private static final int COUNT_BITS = Integer.SIZE - 3;

// 线程数容量,低29位表示有效的线程数, 0001 1111 1111 1111 1111 1111 1111 1111
private static final int CAPACITY = (1 << COUNT_BITS) - 1;

/**
* 大小关系:RUNNING < SHUTDOWN < STOP < TIDYING < TERMINATED,
* 源码中频繁使用大小关系来作为条件判断。
* 1010 0000 0000 0000 0000 0000 0000 0000 运行
* 0000 0000 0000 0000 0000 0000 0000 0000 关闭
* 0010 0000 0000 0000 0000 0000 0000 0000 停止
* 0100 0000 0000 0000 0000 0000 0000 0000 整理
* 0110 0000 0000 0000 0000 0000 0000 0000 终止
*/
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; // 终止

/**
* 功能:获取运行状态
* @param c:ctl值
* @return runState(运行状态)
*/
private static int runStateOf(int c) { return c & ~CAPACITY; }

/**
* 功能:获取当前线程数量
* @param c:ctl值
* @return:workerCount(当前线程数量)
*/
private static int workerCountOf(int c) { return c & CAPACITY; }

/**
* 功能:获取ctl值
* @param rs:运行状态值(runState)
* @param wc:当前线程数量(workerCount)
*/
private static int ctlOf(int rs, int wc) { return rs | wc; }

// 状态c是否小于s
private static boolean runStateLessThan(int c, int s) {
    return c < s;
}

// 状态c是否大于等于s
private static boolean runStateAtLeast(int c, int s) {
    return c >= s;
}

// 状态c是否为RUNNING(小于SHUTDOWN的状态只有RUNNING)
private static boolean isRunning(int c) {
    return c < SHUTDOWN;
}

// 使用CAS增加一个有效的线程
private boolean compareAndIncrementWorkerCount(int expect) {
    return ctl.compareAndSet(expect, expect + 1);
}

// 使用CAS减少一个有效的线程
private boolean compareAndDecrementWorkerCount(int expect) {
    return ctl.compareAndSet(expect, expect - 1);
}

// 减少一个有效的线程
private void decrementWorkerCount() {
    do {} while (! compareAndDecrementWorkerCount(ctl.get()));
}

/** 工作队列:
* ArrayBlockingQueue:列表形式的工作队列,必须要有初始队列大小,有界队列,先进先出。
* LinkedBlockingQueue:链表形式的工作队列,可以选择设置初始队列大小,有界/无界队列,先进先出。
* SynchronousQueue:SynchronousQueue不是一个真正的队列,而是一种在线程之间移交的机制。要将一个元素放入SynchronousQueue中, 必须有另一个线程正在等待接受这个元素. 如果没有线程等待,并且线程池的当前大小小于最大值,那么ThreadPoolExecutor将创建 一个线程, 否则根据饱和策略,这个任务将被拒绝。使用直接移交将更高效,因为任务会直接移交给执行它的线程,而不是被首先放在队列中, 然后由工作者线程从队列中提取任务。只有当线程池是无解的或者可以拒绝任务时,SynchronousQueue才有实际价值。
* PriorityBlockingQueue:优先级队列,有界队列,根据优先级来安排任务,任务的优先级是通过自然顺序或Comparator(如果任务实现了Comparator)来定义的。
* DelayedWorkQueue:延迟的工作队列,无界队列。
*/
private final BlockingQueue<Runnable> workQueue;

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

// 包含线程池中的所有工作线程,只有在mainLock的情况下才能访问,Worker集合
private final HashSet<Worker> workers = new HashSet<Worker>();

private final Condition termination = mainLock.newCondition();

// 跟踪线程池的最大到达大小,仅在mainLock下访问
private int largestPoolSize;

// 总的完成的任务数
private long completedTaskCount;

/**
* 线程工厂,用于创建线程
* DefaultThreadFactory:默认线程工厂,创建一个新的、非守护的线程,并且不包含特殊的配置信息。
* PrivilegedThreadFactory:通过这种方式创建出来的线程,将与创建privilegedThreadFactory的线程拥有相同的访问权限、 AccessControlContext、ContextClassLoader。如果不使用privilegedThreadFactory, 线程池创建的线程将从在需要新线程时调用execute或submit的客户程序中继承访问权限。
* 自定义线程工厂:可以自己实现ThreadFactory接口来定制自己的线程工厂方法。
*/
private volatile ThreadFactory threadFactory;

/**
* (饱和)拒绝策略
* AbortPolicy:中止策略。默认的饱和策略,抛出未检查的RejectedExecutionException。调用者可以捕获这个异常,然后根据需求编写自己的处理代码。
* DiscardPolicy:抛弃策略。当新提交的任务无法保存到队列中等待执行时,该策略会悄悄抛弃该任务。
* DiscardOldestPolicy:抛弃最旧的策略。当新提交的任务无法保存到队列中等待执行时,则会抛弃下一个将被执行的任务,然后尝试重新提交新的任务。(如果工作队列是一个优先队列,那么“抛弃最旧的”策略将导致抛弃优先级最高的任务,因此最好不要将“抛弃最旧的”策略和优先级队列放在一起使用)。
* CallerRunsPolicy:调用者运行策略。该策略实现了一种调节机制,该策略既不会抛弃任务,也不会抛出异常,而是将某些任务回退到调用者(调用线程池执行任务的主线程),从而降低新任务的流程。
* 它不会在线程池的某个线程中执行新提交的任务,而是在一个调用了execute的线程中执行该任务。当线程池的所有线程都被占用,并且工作队列被填满后,下一个任务会在调用execute时在主线程中执行(调用线程池执行任务的主线程)。
* 由于执行任务需要一定时间,因此主线程至少在一段时间内不能提交任务,从而使得工作者线程有时间来处理完正在执行的任务。在这期间,主线程不会调用accept,因此到达的请求将被保存在TCP层的队列中。如果持续过载,那么TCP层将最终发现它的请求队列被填满,因此同样会开始抛弃请求。
* 当服务器过载后,这种过载情况会逐渐向外蔓延开来——从线程池到工作队列到应用程序再到TCP层,最终达到客户端,导致服务器在高负载下实现一种平缓的性能降低。
*/
private volatile RejectedExecutionHandler handler;

/**
* 线程超时时间,当线程数超过corePoolSize时生效,
* 如果有线程空闲时间超过keepAliveTime, 则会被终止
*/
private volatile long keepAliveTime;

// 是否允许核心线程超时,默认false,false情况下核心线程会一直存活。
private volatile boolean allowCoreThreadTimeOut;

// 核心线程数:当前线程池中线程数小于corePoolSize时,即使有线程空闲,依然创建新的线程执行任务
private volatile int corePoolSize;

// 最大线程数
private volatile int maximumPoolSize;

// 默认饱和策略(拒绝策略), 抛异常
private static final RejectedExecutionHandler defaultHandler = new AbortPolicy();

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

/**
* Worker类,每个Worker包含一个线程、一个初始任务、一个任务计算器
*/
private final class Worker extends AbstractQueuedSynchronizer implements Runnable
{
    private static final long serialVersionUID = 6138294804551838833L;
    final Thread thread; // Worker对应的线程
    Runnable firstTask; // 运行的初始任务。
    volatile long completedTasks; // 每个线程的任务计数器
    
    Worker(Runnable firstTask) {
        setState(-1); // 禁止中断,直到runWorker
        this.firstTask = firstTask; // 设置为初始任务
        // 使用当前线程池的线程工厂创建一个线程
        this.thread = getThreadFactory().newThread(this);
    }
    
    // 将主运行循环委托给外部runWorker
    public void run() {
        runWorker(this);
    }
    
    // Lock methods
    //
    // The value 0 represents the unlocked state.
    // The value 1 represents the locked state.
    /**
    * 通过AQS的同步状态来实现锁机制。state为0时代表锁未被获取(解锁状态),
    * state为1时代表锁已经被获取(加锁状态)。
    */
    protected boolean isHeldExclusively() { //
        return getState() != 0;
    }
    
    protected boolean tryAcquire(int unused) { // 尝试获取锁
        if (compareAndSetState(0, 1)) { // 使用CAS尝试将state设置为1,即尝试获取锁
            // 成功将state设置为1,则当前线程拥有独占访问权
            setExclusiveOwnerThread(Thread.currentThread());
            return true;
        }
        return false;
    }
    
    protected boolean tryRelease(int unused) { // 尝试释放锁
        setExclusiveOwnerThread(null); // 释放独占访问权:即将独占访问线程设为null
        setState(0); // 解锁:将state设置为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) {
            }
        }
    }
}

四、线程池工作机制

1.默认情况下,创建完线程池后并不会立即创建线程, 而是等到有任务提交时才会 创建线程来进行处理。(除非调用prestartCoreThread或prestartAllCoreThreads方法)
2.当线程数小于核心线程数时,每提交一个任务就创建一个线程来执行,即使当前有线程处于空闲状态,直到当前线程数达到核心线程数。
3.当前线程数达到核心线程数时,如果这个时候还提交任务,这些任务会被放到队列里,等到线程处理完了手头的任务后,会来队列中取任务处理。
4.当前线程数达到核心线程数并且队列也满了,如果这个时候还提交任务,则会继续创建线程来处理,直到线程数达到最大线程数。
5.当前线程数达到最大线程数并且队列也满了,如果这个时候还提交任务,则会触发饱和策略。
6.如果某个线程的控线时间超过了keepAliveTime,那么将被标记为可回收的,并且当前线程池的当前大小超过了核心线程数时,这个线程将被终止。

五、一些方法

// 使用submit提交时,会运行该方法
public void execute(Runnable command) {
    if (command == null) // 为空校验
        throw new NullPointerException();
    int c = ctl.get(); // 拿到当前的ctl值
    if (workerCountOf(c) < corePoolSize) { // 如果有效的线程数小于核心线程数
        if (addWorker(command, true)) // 则新建一个线程来处理任务(核心线程还不够,创建核心线程)
            return;
        c = ctl.get(); // 拿到当前的ctl值
    }
    // 走到这里说明有效的线程数已经 >= 核心线程数
    if (isRunning(c) && workQueue.offer(command)) {// 如果当前状态是运行, 尝试将任务放入工作队列
        int recheck = ctl.get(); // 再次拿到当前的ctl值
        // 如果再次检查状态不是运行, 则将刚才添加到工作队列的任务移除
        if (! isRunning(recheck) && remove(command))
            reject(command); // 并调用拒绝策略
        else if (workerCountOf(recheck) == 0) // 如果再次检查时,有效的线程数为0,
            addWorker(null, false); // 则新建一个线程(核心线程已满,创建非核心线程)
    }
    // 走到这里说明工作队列已满
    else if (!addWorker(command, false))//尝试新建一个线程来处理任务(非核心)
        reject(command); // 如果失败则调用拒绝策略
}


/**
* 添加一个Worker,Worker包含一个线程和一个任务,由这个线程来执行该任务。
*/
private boolean addWorker(Runnable firstTask, boolean core) {
    retry:
    for (;;) {
        int c = ctl.get(); // c赋值为ctl
        int rs = runStateOf(c); // rs赋值为运行状态
        /**
        * 1.如果池停止或有资格关闭,则此方法返回false;
        * 如果线程工厂在被询问时未能创建线程,它也返回false。
        * 包括以下5种情况:
        * 1).rs为RUNNING,通过校验。
        * 2).rs为STOP或TIDYING或TERMINATED,返回false。
        * (STOP、TIDYING、TERMINATED:已经停止进入最后清理终止,不接受任务不处理队列任务)
        * 3).rs为SHUTDOWN,提交的任务不为空,返回false。
        * (SHUTDOWN:不接受任务但是处理队列任务,因此任务不为空返回false)
        * 4).rs为SHUTDOWN,提交的任务为空,并且工作队列为空,返回false。
        * (状态为SHUTDOWN、提交的任务为空、工作队列为空,则线程池有资格关闭,直接返回false)
        * 5).rs为SHUTDOWN,提交的任务为空,并且工作队列不为空,通过校验。
        * (因为SHUTDOWN状态下刚好可以处理队列任务)
        * ps:shutdown可以看作一个缓冲期,在此期间内,不再接任务,等待手里的任务结束后关门
        */
        if (rs >= SHUTDOWN &&
            ! (rs == SHUTDOWN &&
            firstTask == null &&
            ! workQueue.isEmpty()))
          return false;
        for (;;) {
            int wc = workerCountOf(c); // 拿到有效的线程数
            // 校验有效的线程数是否超过阈值
            if (wc >= CAPACITY ||
                wc >= (core ? corePoolSize : maximumPoolSize))
                return false;
            // 使用CAS将workerCount+1, 修改成功则跳出循环,否则进入下面的状态判断
            if (compareAndIncrementWorkerCount(c))
                break retry;
            c = ctl.get(); // 重新读取ctl
            // 判断当前运行状态,如果不等于上面获取的运行状态rs,
            // 说明rs被其他线程修改了,跳到retry重新校验线程池状态
            if (runStateOf(c) != rs)
                continue retry;
            // 走到这里说明compareAndIncrementWorkerCount失败;
            // 重试内部循环(状态没变,则继续内部循环,尝试使用CAS修改workerCount)
        }
    }
    boolean workerStarted = false; // Worker的线程是否启动
    boolean workerAdded = false; // Worker是否成功增加
    Worker w = null;
    try {
        w = new Worker(firstTask); // 用firstTask和当前线程创建一个Worker
        final Thread t = w.thread; // 拿到Worker对应的线程
        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()); // 加锁的情况下重新获取当前的运行状态
                // 如果当前的运行状态为RUNNING,
                // 或者当前的运行状态为SHUTDOWN并且firstTask为空,则通过校验
                if (rs < SHUTDOWN || (rs == SHUTDOWN && firstTask == null)) {
                    if (t.isAlive()) // 预先校验线程是可以启动的
                        throw new IllegalThreadStateException();
                    workers.add(w); // 将刚创建的worker添加到工作者列表
                    int s = workers.size();
                    if (s > largestPoolSize)
                        largestPoolSize = s;
                    workerAdded = true;
                }
            } finally {
                mainLock.unlock();
            }
            if (workerAdded) { // 如果Worker添加成功,则启动线程执行
                t.start();
                workerStarted = true;
            }
        }
    } finally {
        if (! workerStarted) // 如果Worker的线程没有成功启动
        addWorkerFailed(w); // 则进行回滚, 移除之前添加的Worker
    }
    return workerStarted;
}


/**
* Rolls back the worker thread creation.
* - removes worker from workers, if present
* - decrements worker count
* - rechecks for termination, in case the existence of this
* worker was holding up termination
*/
private void addWorkerFailed(Worker w) { // 回滚Worker的添加,就是将Worker移除
    final ReentrantLock mainLock = this.mainLock;
    mainLock.lock();
    try {
        if (w != null)
        workers.remove(w); // 移除Worker
        decrementWorkerCount(); // 有效线程数-1
        tryTerminate(); // 有worker线程移除,可能是最后一个线程退出需要尝试终止线程池
    } finally {
        mainLock.unlock();
    }
}

/**
* Worker的线程开始执行任务
*/
final void runWorker(Worker w) {
    Thread wt = Thread.currentThread(); // 获取当前线程
    Runnable task = w.firstTask; // 拿到Worker的初始任务
    w.firstTask = null;
    w.unlock(); // allow interrupts
    boolean completedAbruptly = true; // Worker是不是因异常而死亡
    try {
        while (task != null || (task = getTask()) != null) {// Worker取任务执行,第一执行自己的firstTask,之后从队列中拿task,直至getTask返回null
            w.lock(); // 加锁
            /**如果线程池停止,确保线程中断; 如果不是,确保线程不被中断。
            * 在第二种情况下进行重新检查,以便在清除中断的同时处理shutdownNow竞争
            * 线程池停止指运行状态为STOP/TIDYING/TERMINATED中的一种
            */
            if ((runStateAtLeast(ctl.get(), STOP) || // 判断线程池运行状态
                (Thread.interrupted() && // 重新检查
                runStateAtLeast(ctl.get(), STOP))) && // 再次判断线程池运行状态
                !wt.isInterrupted())// 走到这里代表线程池运行状态为停止,检查wt是否中断
                wt.interrupt(); // 线程池的状态为停止并且wt不为中断, 则将wt中断
            try {
                beforeExecute(wt, task);// 执行beforeExecute(默认空,需要自己重写)
                Throwable thrown = null;
                try {
                    task.run(); // 执行任务
                } catch (RuntimeException x) {
                    thrown = x; throw x; //如果抛异常,则completedAbruptly为true
                } catch (Error x) {
                    thrown = x; throw x;
                } catch (Throwable x) {
                    thrown = x; throw new Error(x);
                } finally {
                    afterExecute(task, thrown);// 执行afterExecute(需要自己重写)
                }
            } finally {
                task = null; // 将执行完的任务清空
                w.completedTasks++; // Worker完成任务数+1
                w.unlock();
            }
        }
        completedAbruptly = false; // 如果执行到这里,则worker是正常退出
    } finally {
        processWorkerExit(w, completedAbruptly);// 调用processWorkerExit方法
    }
}

/**
* 返回null的情况:当前线程可以被移除 && keepAliveTime时间内获取不到任务
*/
private Runnable getTask() { // Worker从工作队列获取任务
    boolean timedOut = false; // poll方法取任务是否超时
    for (;;) { // 无线循环
        int c = ctl.get(); // ctl
        int rs = runStateOf(c); // 当前运行状态
        // 如果线程池运行状态为停止,或者可以停止(状态为SHUTDOWN并且队列为空)
        // 则返回null,代表当前Worker需要移除
        if (rs >= SHUTDOWN && (rs >= STOP || workQueue.isEmpty())) {
            decrementWorkerCount(); // 将workerCount - 1
            // 返回null前将workerCount - 1,
            // 因此processWorkerExit中completedAbruptly=false时无需再减
            return null;
        }
        int wc = workerCountOf(c); // 当前的workerCount
        /**
        * 判断当前线程有无超时时间(即是否可以被移除)
        * 如果 allowCoreThreadTimeOut = True:所有线程都有超时时间
        * 如果 workerCount > corePoolSize:当前线程是有超时时间的
        */
        boolean timed = allowCoreThreadTimeOut || wc > corePoolSize;
        // 如果wc超过最大线程数 或者 当前线程会超时并且已经超时,
        // 并且wc > 1 或者 工作队列为空,则返回null,代表当前Worker需要移除
        // timed=线程池允许杀死worker,timeOut=当前worker已超时
        if ((wc > maximumPoolSize || (timed && timedOut))
            && (wc > 1 || workQueue.isEmpty())) { // 确保有Worker可以移除
            if (compareAndDecrementWorkerCount(c))
                // 返回null前将workerCount - 1,
                // 因此processWorkerExit中completedAbruptly=false时无需再减
                return null;
            continue;
        }
        try {
        // 根据线程是否会超时调用相应的方法,poll为带超时的获取任务方法,keepAliveQueue时间内获取不到任务,就返回null
        // take()为不带超时的获取任务方法,会 一直阻塞 直到获取到任务
            Runnable r = timed ? workQueue.poll(keepAliveTime, TimeUnit.NANOSECONDS) : workQueue.take();
            if (r != null)
                return r;
            timedOut = true; // 走到这代表当前线程获取任务超时
        } catch (InterruptedException retry) {
            timedOut = false; // 被中断
        }
    }
}


private void processWorkerExit(Worker w, boolean completedAbruptly) { // Worker的退出
    // 如果Worker是异常死亡(completedAbruptly=true),则workerCount-1;
    // 如果completedAbruptly为false的时候(正常超时退出),则代表task=getTask()等于null,
    // getTask()方法中返回null的地方,都已经将workerCount - 1,所以此处无需再-1
    if (completedAbruptly)
        decrementWorkerCount();
    final ReentrantLock mainLock = this.mainLock;
    mainLock.lock(); // 加锁
    try {
        completedTaskCount += w.completedTasks; // 该Worker完成的任务数加到总完成的任务数
        workers.remove(w); // 移除该Worker
    } finally {
        mainLock.unlock();
    }
    tryTerminate(); // 有Worker线程移除,可能是最后一个线程退出,需要尝试终止线程池
    int c = ctl.get(); // 获取当前的ctl
    if (runStateLessThan(c, STOP)) { // 如果线程池的运行状态还没停止(RUNNING或SHUTDOWN)
        if (!completedAbruptly) { // 如果Worker不是异常死亡
          // min为线程池的理论最小线程数:如果允许核心线程超时则min为0,否则min为核心线程数
          int min = allowCoreThreadTimeOut ? 0 : corePoolSize;
          // 如果min为0,工作队列不为空,将min设置为1,确保至少有1个Worker来处理队列里的任务
          if (min == 0 && ! workQueue.isEmpty())
              min = 1;
          // 当前有效的线程数>=min,直接返回;
          if (workerCountOf(c) >= min)
              return; // replacement not needed
          // 如果代码走到这边,代表workerCountOf(c) < min,此时会走到下面的addWorker方法。
          // 通过getTask方法我们知道,当allowCoreThreadTimeOut为false
          // 并且workerCount<=corePoolSize时,是不会走到processWorkerExit方法的。
          // 因此走到这边只可能是当前移除的Worker是最后一个Worker,但是此时工作
          // 队列还不为空,因此min被设置成了1,所以需要在添加一个Worker来处理工作队列。
        }
        addWorker(null, false); // 添加一个Worker
    }
}


final void tryTerminate() { // 尝试终止线程池
    for (;;) {
        int c = ctl.get();
        // 只有当前状态为STOP 或者 SHUTDOWN并且队列为空,才会尝试整理并终止
        // 1: 当前状态为RUNNING,则不尝试终止,直接返回
        // 2: 当前状态为TIDYING或TERMINATED,代表有其他线程正在执行终止,直接返回
        // 3: 当前状态为SHUTDOWN 并且 workQueue不为空,则不尝试终止,直接返回
        if (isRunning(c) || // 1
            runStateAtLeast(c, TIDYING) || // 2
            (runStateOf(c) == SHUTDOWN && ! workQueue.isEmpty())) // 3
            return;
        // 走到这代表线程池可以终止(通过上面的校验)
        // 如果此时有效线程数不为0, 将中断一个空闲的Worker,以确保关闭信号传播
        if (workerCountOf(c) != 0) { // Eligible to terminate
            interruptIdleWorkers(ONLY_ONE);
            return;
        }
        final ReentrantLock mainLock = this.mainLock;
        mainLock.lock(); // 加锁,终止线程池
        try {
            // 使用CAS将ctl的运行状态设置为TIDYING,有效线程数设置为0
            if (ctl.compareAndSet(c, ctlOf(TIDYING, 0))) {
              try {
                  terminated(); // 供用户重写的terminated方法,默认为空
              } finally {
                  // 将ctl的运行状态设置为TERMINATED,有效线程数设置为0
                  ctl.set(ctlOf(TERMINATED, 0));
                  termination.signalAll();
              }
              return;
          }
        } finally {
            mainLock.unlock();
        }
        // else retry on failed CAS
    }
}

 

posted @ 2019-08-26 09:31  莹狼  阅读(182)  评论(0编辑  收藏  举报