JDK8 线程池核心代码解析

线程池中的一些重要属性
//32-3=29
private static final int COUNT_BITS = Integer.SIZE - 3;

//线程池状态:运行中 这里是-1<<29==>1110 0000 0000 0000 0000 0000 0000 0000 
private static final int RUNNING    = -1 << COUNT_BITS;

///线程池状态:SHUTDOWN 0<<29==>0000 0000 0000 0000 0000 0000 0000 0000
private static final int SHUTDOWN   =  0 << COUNT_BITS;

//线程池状态:STOP 1<<29==>0010 0000 0000 0000 0000 0000 0000 0000
private static final int STOP       =  1 << COUNT_BITS;

//线程池状态:TIDYING 2<<29==>0100 0000 0000 0000 0000 0000 0000 0000
private static final int TIDYING    =  2 << COUNT_BITS;

//线程池状态:TERMINATED 3<<29==>0110 0000 0000 0000 0000 0000 0000 0000
private static final int TERMINATED =  3 << COUNT_BITS;

//结合代码上下文看 表示的是线程数量的最大值
private static final int CAPACITY   = (1 << COUNT_BITS) - 1

//结合上下文代码看 ctl值高3位表示线程池运行状态,低29位表示当前线程池拥有的线程数量  
private final AtomicInteger ctl = new AtomicInteger(ctlOf(RUNNING, 0));

//工作队列
private final BlockingQueue<Runnable> workQueue;

//线程池中存放worker工作线程的地方
private final HashSet<Worker> workers = new HashSet<Worker>();

//线程池工厂 用来创建线程默认是DefaultThreadFactory
private volatile ThreadFactory threadFactory;

//拒绝策略 默认AbortPolicy
private volatile RejectedExecutionHandler handler;

//空闲线程存活时间
private volatile long keepAliveTime;

//控制核心线程数量是否可以被回收 true表示可以回收 false表示不可以回收
private volatile boolean allowCoreThreadTimeOut;

//核心线程数量
private volatile int corePoolSize;

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

通过计算发现,这几个线程池状态存在大小关系的:RUNNING<SHUTDOWN<STOP<TIDYING<TERMINATED

这里介绍下-1<<29、2<<29位的计算过程

-1<<29计算过程

  • 计算-1的原码

-1的原码是1000 0000 0000 0000 0000 0000 0000 0001

  • 计算-1的反码(原码除符号位外,按位取反)

    1000 0000 0000 0000 0000 0000 0000 0001==>1111 1111 1111 1111 1111 1111 1111 1110

  • 计算-1的补码(-1的反码+1)

    1111 1111 1111 1111 1111 1111 1111 1110 + 0001==>1111 1111 1111 1111 1111 1111 1111 1111

  • -1的补码左移29位(每左移一位,低位补0)

    1111 1111 1111 1111 1111 1111 1111 1111 << 29 ==>1110 0000 0000 0000 0000 0000 0000 0000

2<<29位的计算过程

  • 计算2的原码

    2的原码是0000 0000 0000 0000 0000 0000 0000 0010

  • 2左移29位

    0000 0000 0000 0000 0000 0000 0000 0010 << 29 ==>0100 0000 0000 0000 0000 0000 0000 0000

常见方法解析
runStateOf
//获取当前线程池运行状态
private static int runStateOf(int c)     { return c & ~CAPACITY; }

假如入参c的二进制为1110 0000 0000 0000 0000 0000 0000 0011

~CAPACITY ==>~ 0001 1111 1111 1111 1111 1111 1111 1111 ==>1110 0000 0000 0000 0000 0000 0000 0000

1110 0000 0000 0000 0000 0000 0000 0011
1110 0000 0000 0000 0000 0000 0000 0000 ==> ~CAPACITY 
----------------------------------------
1110 0000 0000 0000 0000 0000 0000 0000 ==> c & ~CAPACITY 
workerCountOf
//获取当前线程池线程数量
private static int workerCountOf(int c)  { return c & CAPACITY; }

假如入参c的二进制为1110 0000 0000 0000 0000 0000 0000 0011

1110 0000 0000 0000 0000 0000 0000 0011
0001 1111 1111 1111 1111 1111 1111 1111 ==> CAPACITY 
----------------------------------------
0000 0000 0000 0000 0000 0000 0000 0011 ==> c & CAPACITY 

最终结果0011==>3(十进制)

cltOf

主要用于重置当前线程池ctl值

//rs 线程池状态;wc 线程池线程数量
private static int ctlOf(int rs, int wc) { return rs | wc; }

ctlOf(RUNNING,0)为例进行计算

1110 0000 0000 0000 0000 0000 0000 0000 ==>rs 
0000 0000 0000 0000 0000 0000 0000 0000 ==>wc 0
----------------------------------------
1110 0000 0000 0000 0000 0000 0000 0000 ==> 异或操作
线程池状态比较

runStateLessThan

private static boolean runStateLessThan(int c, int s) {
        return c < s;
}

runStateAtLeast

private static boolean runStateAtLeast(int c, int s) {
        return c >= s;
}

前面分析了 线程池状态有大小之别 因此可以进行比较,在这两个方法在后面比较常用

ThreadPoolExecutor构造函数
public ThreadPoolExecutor(int corePoolSize,// 核心线程数
                              int maximumPoolSize,// 最大线程数
                              long keepAliveTime,// 空闲线程存活时间
                              TimeUnit unit, //时间单位
                              BlockingQueue<Runnable> workQueue,//工作队列
                              ThreadFactory threadFactory, //线程工厂
                              RejectedExecutionHandler handler) {//拒绝策略
  			//合法性验证 这里主要 核心线程数要>=最大线程数
        if (corePoolSize < 0 ||
            maximumPoolSize <= 0 ||
            maximumPoolSize < corePoolSize ||
            keepAliveTime < 0)
            throw new IllegalArgumentException();
        //对工作队列、线程工厂、拒绝策略进行验证
        if (workQueue == null || threadFactory == null || handler == null)
            throw new NullPointerException();
        this.acc = System.getSecurityManager() == null ?
                null :
                AccessController.getContext();
        this.corePoolSize = corePoolSize;
        this.maximumPoolSize = maximumPoolSize;
        this.workQueue = workQueue;
        this.keepAliveTime = unit.toNanos(keepAliveTime);
        this.threadFactory = threadFactory;
        this.handler = handler;
    }
线程池工作单元Worker类解析
常用属性
//worker中封装的工作线程
final Thread thread;
//线程执行任务
Runnable firstTask;
//当前worker所完成任务数量
volatile long completedTasks;
常用方法解析
private final class Worker
            extends AbstractQueuedSynchronizer
            implements Runnable

首先看下Worker类的继承、实现关系。Worker继承了AQS,说明类中会加锁、解锁等操作,并且实现了Runnable接口,自然要有run方法去执行任务。

了解过AQS的都知道,AQS有两种模式:独占、共享。而这里使用的是独占模式,即必须等线程A释放锁后 线程B才能抢占到锁。

AQS中state表示同步状态 可以表示被抢占资源,当state=0时表示锁未被占用,state>0 表示被占用; state<0 表示初始状态 这种情况不能抢占锁

关于AQS内容 这里暂不深入 点到为止

lock

//Worker#lock
public void lock()        { acquire(1); }
//AbstractQueuedSynchronizer#acquire
public final void acquire(int arg) {
        //抢占锁成功 正常返回;抢占锁失败 将当前线程当做独占Node插入到等待队列 
   			// 等待其他线程释放锁后唤醒它
        //tryAcquire会被子类重写
        if (!tryAcquire(arg) &&
            acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
            selfInterrupt();
    }
protected boolean tryAcquire(int unused) {
            //CAS成功 说明成功抢占锁
            if (compareAndSetState(0, 1)) {
                //将当前线程作为独占锁线程
                setExclusiveOwnerThread(Thread.currentThread());
                return true;
            }
            return false;
}

unlock

//Worker#unlock
public void unlock()      { release(1); }
//AbstractQueuedSynchronizer#release
public final boolean release(int arg) {
        //如果资源释放完毕,则唤醒等待队列头结点;此时头节点的下一个等待节点会不断地自旋尝试获取锁
        if (tryRelease(arg)) {
            Node h = head;
            if (h != null && h.waitStatus != 0)
                unparkSuccessor(h);
            return true;
        }
        return false;
    }
//Worker#tryRelease
protected boolean tryRelease(int unused) {
  					//独占线程置为null
            setExclusiveOwnerThread(null);
  					//state置为0
            setState(0);
            return true;
       }

run

public void run() {
  					//当工作线程启动后 就会执行这个方法去完成任务
            runWorker(this);
        }
execute

线程池提交任务的方式主要有两种: submit、execute

submit主要逻辑也是调用execute,因此我们来看下execute实现的大体逻辑

因为execute方法中有调用到addWorker(),为方便理解execute方法,这里先大致看下addWorker()的实现

addWorker
//firstTask 线程执行的任务 可控
//core,true表示创建核心线程,false表示创建非核心线程
private boolean addWorker(Runnable firstTask, boolean core) {
        retry:
        for (;;) {
            int c = ctl.get();
          	//获取线程池运行状态
            int rs = runStateOf(c);

            //rs>=SHUTDOWN有几种可能:SHUTDOWN STOP TIDYING TERMINATED
          	//! (rs == SHUTDOWN &&firstTask == null && ! workQueue.isEmpty()) 这个判断条件有些绕 我们整体理解下:当线程池状态不是运行中并且工作队列为空时 不允许再创建Worker;但是当工作队列不为空时即便线程池状态不是运行中 也运行创建worker,帮助处理工作队列的任务
            if (rs >= SHUTDOWN &&
                ! (rs == SHUTDOWN &&
                   firstTask == null &&
                   ! workQueue.isEmpty()))
                return false;
            for (;;) {
                //线程池工作线程数量
                int wc = workerCountOf(c);

                //如果工作线程数大于核心线程数或最大线程池数量 则无法添加Worker
                if (wc >= CAPACITY ||
                    wc >= (core ? corePoolSize : maximumPoolSize))
                    return false;
                // 走到这里 说明校验通过 可以创建worker 并将工作线程数量+1
                if (compareAndIncrementWorkerCount(c))
                    //跳出retry循环
                    break retry;
               //获取最新的ctl
                c = ctl.get();  // Re-read ctl
                // 这里线程池状态与rs不等,说明在addWorker期间 线程池状态发生过状态,比如调用过SHUTDOWN等
                if (runStateOf(c) != rs)
                    continue retry;
                // else CAS failed due to workerCount change; retry inner loop
            }
        }
				//worker是否启动成功
        boolean workerStarted = false;
        //worker是否添加成功
        boolean workerAdded = false;
        Worker w = null;
        try {
            //新建Worker对象
            w = new Worker(firstTask);
            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());
										
                    //rs<SHUTDWON ==> 线程池运行状态为RUNNING 可以创建Worker
                    //rs == SHUTDOWN && firstTask == null 条件成立 说明此时创建的Worker是帮助处理工作队列任务的
                    if (rs < SHUTDOWN ||
                        (rs == SHUTDOWN && firstTask == null)) {
                        //如果在启动线程前 发现线程已经存活 
                        if (t.isAlive()) // precheck that t is startable
                            throw new IllegalThreadStateException();
                        //将worker添加到HashSet中
                        workers.add(w);
                        int s = workers.size();
                        //如果线程池Worker数量> largestPoolSize,则更新largestPoolSize值
                        if (s > largestPoolSize)
                            largestPoolSize = s;
                        //Worker添加成功
                        workerAdded = true;
                    }
                } finally {
                   //解锁
                    mainLock.unlock();
                }
                //如果worker添加成功则启动线程
                if (workerAdded) {
                    t.start();
                    //线程启动成功标记
                    workerStarted = true;
                }
            }
        } finally {
            if (! workerStarted)
                //处理worker添加失败的后续逻辑
                addWorkerFailed(w);
        }
        return workerStarted;
    }

该方法主要涉及以下逻辑:

1.检查线程池状态,判断是否再可以创建worker

2.检查线程池数量,判断是否再可以创建worker

3.创建worker

  • 新建Worker对象 将其添加到HashSet,线程池数量+1
  • 线程添加成功,即启动线程
    • 线程启动成功,即正常退出 该方法响应true
    • 线程启动失败,执行worker添加失败的逻辑
      • 线程池数量-1
      • 从线程池集合HashSet中移除该worker
      • 清除线程池中的空闲线程
public void execute(Runnable command) {	
  			//对任务进行非空判断
        if (command == null)
            throw new NullPointerException();
        // 获取ctl 高三位 线程池状态;低29位 线程池数量
        int c = ctl.get();
        //如果线程池数量小于核心线程数
        if (workerCountOf(c) < corePoolSize) {
          	//创建工作线程,并将command作为任务,创建成功即返回 ⭐️
            if (addWorker(command, true))
                return;
          	//程序走到这里,说明addWorker()失败了,失败原因大致有两种
          	//1.当前线程池数量已经超过核心线程数,不能再创建核心线程
            //2.在创建核心线程时,外部有其他操作调用了线程池SHUTDOWN/SHUTDOWNNOW等 使此时线程池运行状态发生了改变
            //获取最新的线程池ctl属性值
            c = ctl.get();
        }
        //程序走到这里,有两种可能:
  			//1、线程池数量达到了核心线程数;2、addWorker()新建worker失败了
        //isRunning(c) 成立 说明线程池状态为运行中,说明只是线程池数量达到了核心线程数
        //workQueue.offer(command) 成立 说明 任务成功被添加到工作队列
        if (isRunning(c) && workQueue.offer(command)) {
            //获取最新的线程池ctl属性值
            int recheck = ctl.get();
            //! isRunning(recheck) 条件成立 说明线程池运行状态被改变了,可能外部调用了SHUTDOWN/SHUTDOWNNOW,因此需要将添加到工作队列的任务给删除
            //remove(command) 如果删除成功,说明该任务提交到工作队列 还没有被线程处理
            if (! isRunning(recheck) && remove(command))
                //对任务执行拒绝策略
                reject(command);
            //如果线程池是运行状态 或者 任务删除失败的情况下 发现线程池线程数量为0
            //这里会创建一个非核心线程 
            // 1.保障线程池在运行状态下 有线程在工作
            // 2.非运行状态下 工作队列中的任务有线程能去执行
            else if (workerCountOf(recheck) == 0)
                addWorker(null, false);
        }
        //当线程池非运行状态 或者工作队列满时 程序会走到这里
        //如果是工作队列满了,线程池会继续创建非核心线程数至maximumPoolSize,达到了maximumPoolSize后创建失败,会走到拒绝策略
        //如果是非运行状态,线程池就不能再提交任务了,因此addWorker(command,false)也会失败,会走到拒绝策略
        else if (!addWorker(command, false))
            reject(command);
    }

execute()方法的执行逻辑进行总结:

1、对提交上来的任务进行非空交易

2、当线程池线程数量小于核心线程数量时,创建核心线程

  • 创建成功,程序执行结束
  • 当线程池数量超过核心线程数或在创建核心线程时线程池变为非RUNNING状态,都会导致核心线程创建失败

3、当线程池数量超过核心线程数时,会将任务放到工作队列

  • 当检测到线程池变为非RUNNING时,从工作队列删除添加的任务 并执行拒绝策略
  • 线程池运行过程中发现线程数为0,则创建非核心线程 保障线程池中有线程在工作

4、当工作队列满时,尝试创建非核心线程

  • 线程池线程数量达到maximumPoolSize,非核心线程创建失败,走拒绝策略
  • 当线程池状态是SHUTDOWN/SHUTDOWNNOW时,不允许再提交任务 会走拒绝策略
runWorker()

前面的execute()方法已经把任务提交到线程池了,这里我们看下任务是怎么执行的?

实际上,执行任务被封装在Worker,而Worker实现类Runnable接口,因此执行任务入口在run方法

//Worker#run
public void run() {
            runWorker(this);
        }
final void runWorker(Worker w) {
        //获取当前线程
        Thread wt = Thread.currentThread();
  			//获取待执行任务
        Runnable task = w.firstTask;
        w.firstTask = null;
        //Worker构造函数 构造state=-1
  			//这里执行unlock 将独占线程置为null 将state由-1==>0 为w.lock()做准备
        w.unlock(); // allow interrupts
        boolean completedAbruptly = true;
        try {
            //这里Worker执行的任务有两个来源:1、线程池直接提交过来的 2、工作队列的
            while (task != null || (task = getTask()) != null) {
               //对worker加锁
                w.lock();

                // (runStateAtLeast(ctl.get(), STOP) 如果成立 说明线程池状态可能是STOP、TIDYING、TERMINATED
                //Thread.interrupted() 获取线程中断状态 并重置中断标记位为false
                //这个if块主要逻辑是 当线程池运行状态是STOP、TIDYING、TERMINATED 并且被中断了,那么要响应中断
                if ((runStateAtLeast(ctl.get(), STOP) ||
                     (Thread.interrupted() &&
                      runStateAtLeast(ctl.get(), STOP))) &&
                    !wt.isInterrupted())
                    // 这里需要注意 当worker取工作队列取不到任务被阻塞时,若worker响应中断了 会退出阻塞状态 
                    wt.interrupt();
                try {
                    //空方法 我们可以自己重写
                    beforeExecute(wt, task);
                    Throwable thrown = null;
                    try {
                        //这里就是调用Runnable#run方法了
                        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 
                    task = null;
                    //完成任务数+1
                    w.completedTasks++;
                    //解锁
                    w.unlock();
                }
            }
            //当没有任务要执行时,程序逻辑来到这里,紧接着就是执行Worker退出的逻辑;
            //但是 当在执行任务过程中抛出了异常 则会执行执行到下面finally,
            //所以 这个字段也可以标识 是否正常完成。false表示正常完成,true表示出异常了
            completedAbruptly = false;
        } finally {
            processWorkerExit(w, completedAbruptly);
        }
    }

总结一下这个方法的主要逻辑:

1、如果线程池提交任务为空或者工作队列任务为空 直接执行worker退出逻辑

2、若线程池状态为STOP、TIDYING、TERMINATED 并且Worker被中断了 则触发中断

3、正常执行任务

4、任务执行完毕,执行worker退出逻辑

processWorkerExit

当任务在执行完毕 会触发worker退出逻辑

//w 表示要退出的worker
//completedAbruptly true表示异常退出,false表示正常退出
private void processWorkerExit(Worker w, boolean completedAbruptly) {
        //异常退出时,线程数-1
        if (completedAbruptly) // If abrupt, then workerCount wasn't adjusted
            decrementWorkerCount();

        final ReentrantLock mainLock = this.mainLock;
        mainLock.lock();
        try {
            //如果是正常退出 更新完成任务数
            completedTaskCount += w.completedTasks;
            //从hashSet中移除该worker
            workers.remove(w);
        } finally {
            mainLock.unlock();
        }
				//这个方法会清理空闲线程 并修改线程池状态,后面详细说
        tryTerminate();

        int c = ctl.get();
        // runStateLessThan(c, STOP) 成立 说明当前线程池运行状态为RUNNING、SHUTDOWN
        if (runStateLessThan(c, STOP)) {
            //如果是正常退出
            if (!completedAbruptly) {
                //allowCoreThreadTimeOut 标识核心线程是否可回收,true标识超时可回收,false 则不可
                // 这里是获取当前线程池最少拥有的线程数量
                int min = allowCoreThreadTimeOut ? 0 : corePoolSize;
                // 当最少线程数为0 且工作队列不为空 那要给一个线程去执行工作队列任务
                if (min == 0 && ! workQueue.isEmpty())
                    min = 1;
                //当线程池线程数>最少线程池min时,说明线程池中还有线程 不需要额外创建线程
                if (workerCountOf(c) >= min)
                    return; // replacement not needed
            }
            // 程序执行到这里 有两种前提条件:1、线程池中没有线程了 但是工作队列还有任务 因此要创建worker去执行 
            //2、触发processWorkerExit方法的worker是执行异常退出的,因此要再创建一个worker接着去执行任务
            addWorker(null, false);
        }
    }

总结一下这个方法的主要逻辑:

1、如果worker是正常退出的

  • 更新完成任务数,并从hashet中移除该worker
  • 当线程池运行状态是RUNNING、SHUTDOWN,线程池线程数量为0 但是还有任务要执行时 则添加worker去执行

2、如果worker是异常退出的

  • 线程池线程数量-1
  • 新建一个worker 接着去执行任务
getTask

这里再来看一下从工作队列取任务的逻辑实现

private Runnable getTask() {
        boolean timedOut = false; // Did the last poll() time out?

        for (;;) {
            int c = ctl.get();
            int rs = runStateOf(c);

            // 条件成立有两种可能:1、rs >= SHUTDOWN && rs>=STOP ==>线程池已停止了
            //2.rs >= SHUTDOWN && workQueue.isEmpty() 当前线程池状态为SHUTDOWN 并且工作队列为空
            if (rs >= SHUTDOWN && (rs >= STOP || workQueue.isEmpty())) {
                //线程池数量-1
                decrementWorkerCount();
                //取不到任务
                return null;
            }
						//线程池线程数量
            int wc = workerCountOf(c);

            // 当允许核心线程被回收 或 线程池线程数大于核心线程数时 返回true
            boolean timed = allowCoreThreadTimeOut || wc > corePoolSize;
          
						// (wc > maximumPoolSize || (timed && timedOut) 当线程池线程数量大于最大线程池数量 或 任务获取超时
            //(wc > 1 || workQueue.isEmpty()) 线程池线程数量不为0 但是工作队列为空
            if ((wc > maximumPoolSize || (timed && timedOut))
                && (wc > 1 || workQueue.isEmpty())) { 
                //线程池线程数量-1 
                if (compareAndDecrementWorkerCount(c))
                    return null;
                continue;
            }

            try {
                //获取任务,根据timed属性值不同 获取任务时 可选支持超时机制或不支持超时机制
                Runnable r = timed ?
                    workQueue.poll(keepAliveTime, TimeUnit.NANOSECONDS) :
                    workQueue.take();
                if (r != null)
                    return r;
                //任务获取超时
                timedOut = true;
            } catch (InterruptedException retry) {
                timedOut = false;
            }
        }
    }

该方法主要逻辑总结:

当worker获取执行任务时

  • 如果线程池已停止或者工作队列为空 则不须再执行任务了,并将线程池线程数量减1
  • 如果线程池线程数量大于最大线程数量 或者 获取任务超时 或者工作队列为空了,则不须再执行任务了,并将线程池线程数量减1
  • 正常从工作队列取任务 并返回
shutdown

该方法会关闭线程池,将线程池运行状态置为SHUTDOWN。不再接受新的任务,会将以前提交的任务给执行了

public void shutdown() {
        final ReentrantLock mainLock = this.mainLock;
        mainLock.lock();
        try {
            checkShutdownAccess();
            //线程池运行状态置为SHUTDOWN
            advanceRunState(SHUTDOWN);
            //中断空闲线程
            interruptIdleWorkers();
            onShutdown(); // hook for ScheduledThreadPoolExecutor
        } finally {
            mainLock.unlock();
        }
        tryTerminate();
    }
interruptIdleWorkers
private void interruptIdleWorkers(boolean onlyOne) {
        final ReentrantLock mainLock = this.mainLock;
        mainLock.lock();
        try {
            //遍历worker集合
            for (Worker w : workers) {
                Thread t = w.thread;
                //!t.isInterrupted() 成立的话  说明线程没有被中断
                //w.tryLock() 成立的话 说明成功获取锁 也说明该worker没有执行runWorker方法 是空闲着的
                if (!t.isInterrupted() && w.tryLock()) {
                    try {
                        //中断该线程
                        t.interrupt();
                    } catch (SecurityException ignore) {
                    } finally {
                        w.unlock();
                    }
                }
                //根据入参onlyOne的值 来决定是中断其中一个空闲worker,还是将全部空闲worker全部中断
                if (onlyOne)
                    break;
            }
        } finally {
            mainLock.unlock();
        }
    }

这里需要注意一下,work.thread 可能会在getTask()方法,从工作队列取任务时被阻塞。如果worker已经是空闲状态,那么w.thread被中断,则work.thread会从getTask()取任务处被唤醒,最终因获取不到任务 而导致worker退出线程池。

tryTerminate

这个方法主要从事线程池终止的操作。

当线程池处于SHUTDOWN状态而且工作队列为空 或者 线程池处于STOP 状态并且线程池为空,那么线程池就可以终止了。如果在终止线程池时发现线程池线程数量不为0,则中断这些线程

final void tryTerminate() {
        for (;;) {
            //获取ctl
            int c = ctl.get();
            // isRunning(c) 如果线程池处于运行中 则退出终止操作
            //runStateAtLeast(c, TIDYING) 如果条件成立 说明有其他线程在终止线程池,当前线程可以退出
            //(runStateOf(c) == SHUTDOWN && ! workQueue.isEmpty() 如果还有任务没执行,则退出终止操作
            if (isRunning(c) ||
                runStateAtLeast(c, TIDYING) ||
                (runStateOf(c) == SHUTDOWN && ! workQueue.isEmpty()))
                return;
            //当决定要终止时,发现线程池线程数量不是0 则中断空闲线程,这里ONLY_ONE=true 即中断全部空闲线程
            if (workerCountOf(c) != 0) { // Eligible to terminate
                interruptIdleWorkers(ONLY_ONE);
                return;
            }

            final ReentrantLock mainLock = this.mainLock;
            mainLock.lock();
            try {
                // 将线程池运行状态设置为TIDING,与前面runStateAtLeast(c, TIDYING) 呼应上了
                if (ctl.compareAndSet(c,  ctlOf(TIDYING, 0))) {
                    try {
                        //空方法
                        terminated();
                    } finally {
                        //将线程池运行状态设置为TERMINATED
                        ctl.set(ctlOf(TERMINATED, 0));
                        //唤醒线程,纵观全局 应该是唤醒调用了awaitTermination方法的线程
                        termination.signalAll();
                    }
                    return;
                }
            } finally {
                mainLock.unlock();
            }
            // else retry on failed CAS
        }
    }

对该方法进行总结:

1、若线程池处于运行状态 则线程池不进行终止

2、当线程池SHUTDOWN 但是工作队列有任务时,则线程池不进行终止

3、当有其他线程在终止线程池时,当前线程退出终止操作

4、终止线程池,将状态置为TERMINATED,并唤醒线程

shutdownNow
public List<Runnable> shutdownNow() {
        List<Runnable> tasks;
        final ReentrantLock mainLock = this.mainLock;
        mainLock.lock();
        try {
            checkShutdownAccess();
            //线程池状态置为STOP
            advanceRunState(STOP);
            //中断所有线程
            interruptWorkers();
            //将工作队列中未执行的任务拿出来 返回出去
            tasks = drainQueue();
        } finally {
            mainLock.unlock();
        }
        //在这里执行线程池终止操作 
        tryTerminate();
        //返回未执行的任务
        return tasks;
    }
awaitTermination

调用了线程池的shutdown()与shutdownNow()方法之后,用户程序都不会主动等待线程池关闭完成,如果需要等待线程池关闭完成,需要调用awaitTermination()进行主动等待

public boolean awaitTermination(long timeout, TimeUnit unit)
        throws InterruptedException {
        long nanos = unit.toNanos(timeout);
        final ReentrantLock mainLock = this.mainLock;
        mainLock.lock();
        try {
            for (;;) {
                //线程池运行状态为TERMINATED
                if (runStateAtLeast(ctl.get(), TERMINATED))
                    return true;
                if (nanos <= 0)
                    return false;
                //条件队列 在这里等待
                //当线程池运行状态变为TERMINATED,会在tryTerminate 唤醒当前线程
              nanos = termination.awaitNanos(nanos);
            }
        } finally {
            mainLock.unlock();
        }
    }

如果线程池完成关闭,awaitTermination()方法将会返回true,否则当等待时间超过指定时间后将会返回false。如果线程池完成关闭,awaitTermination()方法将会返回true,否则当等待时间超过指定时间后将会返回false。

这里引用一段关闭线程池的代码

if(!threadPool.isTerminated()){
  try{
    for(int i=0;i<1000;i++){ //循环关闭1000次 每次等待10毫秒
      if(threadPool.awaitTermination(10,TimeUnit.MILLISECONDS)){
        break;
      }
      threadPool.shutdownNow();
    }
  }catch(InterruptedException e){
    
  }catch(Throwable e){
    
  }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值