java 线程池源码

148 阅读7分钟

重要变量介绍

//首先要知道一点,线程池状态跟线程池线程数量由一个整数控制,二进制标识,高三位是
//表示状态,底29位表示线程数量
// ctl 原子操作 ,表示线程池状态+线程池数量
//ctlOf(RUNNING, 0) 初始值,线程数量为0,线程池状态 运行中
private final AtomicInteger ctl = new AtomicInteger(ctlOf(RUNNING, 0));
//32-3=29 表示低位29是线程池线程数量
private static final int COUNT_BITS = Integer.SIZE - 3;
//1左移29位 然后减1
//从29位开始都是1
private static final int CAPACITY   = (1 << COUNT_BITS) - 1;
// -1左移29位 高三位都是1,低29位都是0 表示线程池状态运行中
private static final int RUNNING    = -1 << COUNT_BITS;
// 0 左移 19 32位都是0 调用  shutdown()方法之后
//表示线程池即将关闭,不接受新任务,但是会执行剩余任务
private static final int SHUTDOWN   =  0 << COUNT_BITS;
//1左移29位  001 00000000000000000000000000000
//表示线程池 关闭了,调用shutdownnow()方法的时候,状态转变
//不接受新任务,停止正在执行的任务
private static final int STOP       =  1 << COUNT_BITS;
//2左移29位置  010 00000000000000000000000000000
//线程池即将关闭,任务都执行完或者都停止了,没有需要执行的任务也灭有正在执行的任务
private static final int TIDYING    =  2 << COUNT_BITS;
///3左移29位置  011 00000000000000000000000000000
//当线程池状态为 TIDYING 然后执行了 terminated() 钩子方法之后,状态变为 TERMINATED
//这个应该是终态了
private static final int TERMINATED =  3 << COUNT_BITS;

//CAPACITY 取反 & c(c是ctl.get()出来的结果,也就是线程数量+线程池状态)
//CAPACITY 取反 得到高位3位都是1 低29位都是0
//c & 上 CAPACITY 取反 得到 c 高3位的值,其实就是得到线程池状态
private static int runStateOf(int c)     { return c & ~CAPACITY; }
//类似 runStateOf 得到 c 低29位值,也就是线程池数量
private static int workerCountOf(int c)  { return c & CAPACITY; }
//线程池数量+线程池状态
private static int ctlOf(int rs, int wc) { return rs | wc; }
 

上面介绍的是线程池数量跟状态的表示,32位二进制,高三位表示线程池状态,低29位表示线程池线程数量。

线程池状态变化

RUNNING->SHUTDOWN:运行中,调用shutdown方法,开始停止接受新任务,把线程池中的所有任务执行完。

RUNNING->STOP:运行中,调用shutdownnow方法,停止接受新任务,清空任务队列,停止正在执行的任务,所以 shutdown 跟 shutdownnow 不一样的就是 shutdownnow,会清空队列,而且停止正在执行的任务

SHUTDOWN->STOP:任务清空了

构造方法

 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;
   }
1.corePoolSize:核心线程数量

2.maximumPoolSize:最大线程数量

3.keepAliveTime: 超过最大线程数量,线程存活时间

4.unit:搭配 keepAliveTime 表示单位

5.workQueue:阻塞队列,一般有 ArrayBlockingQueue、LinkedBlockingQueue、SynchronousQueue

6.handler:拒绝策略

7.threadFactory :线程生成工厂

worker

故名思意就是打工人,负责执行任务的类,其实也就是线程

//继承 aqs ,可以当作一把锁
//失效 runable 有run方法,可以当作线程执行任务
private final class Worker
    extends AbstractQueuedSynchronizer
    implements Runnable
{
    //当前线程
    final Thread thread;
    //第一个任务,这个解释下,这个有两种情况
    //1.新建worker的时候传入一个task任务,让woker执行,firsttask 不为空
    //2.firsttask 为空,需要不断从队列中获取任务执行
    Runnable firstTask;
    //这个线程完成的任务数量
    volatile long completedTasks;

    // 构造方法,设置 firsttask 跟 调用线程工厂创建一个新线程
    Worker(Runnable firstTask) {
        setState(-1); // inhibit interrupts until runWorker
        this.firstTask = firstTask;
        this.thread = getThreadFactory().newThread(this);
    }

   //run方法 真正干活的地方
    public void run() {
        runWorker(this);
    }

execute 方法

public void execute(Runnable command) {
   if (command == null)
       throw new NullPointerException();
    // c:线程池数量+线程池状态
   int c = ctl.get();
   //如果目前线程池的线程数量 小于 核心线程数量 增加任务
   if (workerCountOf(c) < corePoolSize) {
        //增加任务,如果添加任务成功就返回
       if (addWorker(command, true))
           return;
       //添加任务失败,可能存在并发,当前线程数量已经大于核心线程
       //重新获取 c 走下面逻辑
       c = ctl.get();
   }
   //添加核心线程失败或者当前线程数量大于核心线程数量
   //判断当前线程状态是否 在运行中,如果在运行中 就把任务放到队列中
   //这边写的蛮巧妙的,在开发中好像都没这么写过,if中如果 isRuning 为ture
   //就执行 workqueue.offer
   if (isRunning(c) && workQueue.offer(command)) {
   //添加队列成功之后,再次检查线程池状态
       int recheck = ctl.get();
       //如果线程池不为运行中,就移除刚才放入列队的任务
       //如果不为运行中,就不接受新任务了,所以移除
       if (! isRunning(recheck) && remove(command))
       //移除成功,执行拒绝策略
           reject(command);
       //如果线程运行中,而且当前线程数量为0,就增加新任务
       //为什么要增加这一步,可能核心线程为0,添加任务到队列之后
       //线程为0了,这时候就没有线程去轮询到队列拿任务来执行,所以要新建woker
       //这边的addwokrer 要注意跟上面的 addworker 不一样
       //第一个入参是任务为空,因为新加woker 要从队列拿,所以为空
       //第二个参数false ,表示是否核心线程,这边因为第一个if没走到,所以不是核心线程
       else if (workerCountOf(recheck) == 0)
           addWorker(null, false);
   }
   //走到这里,说明添加任务到队列失败了,也就是队列满了,队列满了,就增加任务
   //注意第二个参数false,表示非核心线程
   else if (!addWorker(command, false))
       //如果添加任务失败,执行拒绝策略
       reject(command);
}

从上面三个if可以大概看出添加线程到线程池的流程:1、线程池数量小于核心线程:新增线程。 2、线程池数量不小于核心线程,也就是核心线程满了,把任务放放到任务队列 3、任务队列满了,新增线程为非核心线程,新增失败,也就是最大线程满了,执行拒绝策略。 说到执行拒绝策略,这边可以看到有两个地方调用 1、核心线程满了,放到队列成功,但是线程池状态不是运行中 2、最大线程满了,也执行拒绝策略

addWorker

private boolean addWorker(Runnable firstTask, boolean core) {
    retry:
    //第一层for循环
    for (;;) {
        int c = ctl.get();
        int rs = runStateOf(c);

        // 这是一个校验,校验不过就返回false 表示添加任务失败。什么时候校验不过
        //1. rs >= SHUTDOWN : 除了runing rs 都是大于等于 shutdown,也就是非runing
        //2.满足下面其中一个条件就行
        //2.1 rs不是shutdown,如果不是 shutdown ,那就是大于 shutdown,说明此时
        //线程不能再接受新任务,不执行现有任务,所以返回false没问题
        //2.2 firsttask != null 说明此时是shutdown,但是是新增任务,如果是shutdown
        //就不新增任务了,而firsttask不为空,表示新增任务,所以返回false表示不接受
        //2.3 workqueue 是空队列,说明此时是shutdown,firsttask 为空,不是新增任务
        //那就是要从队列中执行任务,但是队列为空,所以返回false
        if (rs >= SHUTDOWN &&
            ! (rs == SHUTDOWN &&
               firstTask == null &&
               ! workQueue.isEmpty()))
            return false;
        //上面校验成功,这是第二层for循环 
        for (;;) {
            int wc = workerCountOf(c);
            //如果工作线程大于线程最大数量 或者 线程数量大于核心数量/最大数量
            //这个根据传入的参数 core 判断此时是要创建核心线程还是非核心线程
            //就返回false 表示新增线程失败
            if (wc >= CAPACITY ||
                wc >= (core ? corePoolSize : maximumPoolSize))
                return false;
            //如果新增线程数量允许,那就cas新增工作线程数量    
            if (compareAndIncrementWorkerCount(c))
            //cas成功,就退出两层for循环,到真的新增worker的逻辑
                break retry;
            //cas失败,表示有并发    
            c = ctl.get();  // Re-read ctl
            //检查线程状态是否变化,如果变化了,跳到第一次线程再次检查线程状态
            //如果线程状态没有变化,那就是工作线程数量变化了,第二次循环再来一次cas
            if (runStateOf(c) != rs)
                continue retry;
            // else CAS failed due to workerCount change; retry inner loop
        }
    }

    boolean workerStarted = false;
    boolean workerAdded = false;
    Worker w = null;
    try {
    //new 一个工作线程
        w = new Worker(firstTask);
        final Thread t = w.thread;
        if (t != null) {
        //全局锁
            final ReentrantLock mainLock = this.mainLock;
            mainLock.lock();
            try {
              .
                int rs = runStateOf(ctl.get());
                //rs < SHUTDOWN  表示 线程正常运行
                //rs == SHUTDOWN && firstTask == null
                //表示线程虽然 shutdown 但是firsttask为空,可以从队列拿任务来执行
                //以上两种情况都可以执行任务
                if (rs < SHUTDOWN ||
                    (rs == SHUTDOWN && firstTask == null)) {
                    if (t.isAlive())  
                        throw new IllegalThreadStateException();
                        //往线程list添加线程
                    workers.add(w);
                    //当前线程的大小
                    int s = workers.size();
                    //largestPoolSize 表示该线程出现过最大的线程数量
                    //因为线程池线程数量一直变化,这个是再记录,具体用处不知道
                    if (s > largestPoolSize)
                        largestPoolSize = s;
                    workerAdded = true;
                }
            } finally {
            //全局锁解锁
                mainLock.unlock();
            }
            if (workerAdded) {
            //开始线程,执行任务,后续流程看这个
                t.start();
                workerStarted = true;
            }
        }
    } finally {
    //添加任务失败,需要把线程数量啥的减一
        if (! workerStarted)
            addWorkerFailed(w);
    }
    return workerStarted;
}

addworker这个方法首先有两个for循环。第一个循环:校验线程池状态是否正常,如果不正常就返回fasle,表示执行失败 第二个循环:校验线程数数量是否正常,如果正常cas修改线程池数量,cas失败则还有两种情况,第一种状态变化了,第二种数量变化了。所以两层循环一个目的是校验,另一个目的是cas修改线程数量。执行完循环之后,真的开始创建线程,开启线程,然后最后再finally 中 判断如果新增线程失败,通过 addWorkerFailed 来处理

addWorkerFailed

//添加任务失败后需要处理的
private void addWorkerFailed(Worker w) {
//全局锁
    final ReentrantLock mainLock = this.mainLock;
    mainLock.lock();
    try {
    //如果任务不为空,往任务列表移除任务
        if (w != null)
            workers.remove(w);
        //最开始有cas新增线程数量,线程cas减少线程数量    
        decrementWorkerCount();
        //因为新增任务失败,尝试 terminate 线程池,这个后面说
        tryTerminate();
    } finally {
        mainLock.unlock();
    }
}

runworker

//上面添加完线程之后,start线程,然后到run方法,run方法执行 runworker方法
//也就是线程真正干活的地方
final void runWorker(Worker w) {
//当前线程
    Thread wt = Thread.currentThread();
    //第一个任务,可能为空,为空就从队列取
    Runnable task = w.firstTask;
    //把当前第一个任务值为空
    w.firstTask = null;
    //这个不是全局锁了,是当前线程一个锁,不知道为啥一来就 unlock 
    w.unlock(); // allow interrupts
    boolean completedAbruptly = true;
    try {
      //while循环,两个情况,第一个i情况,当前worker 有第一个任务,直接执行
      //第二个情况,从队列拿任务,任务不为空,拿任务来执行
        while (task != null || (task = getTask()) != null) {
        //进入就锁住,己住这个
            w.lock();
            // 如果线程池状态大于等stop,说明此时不能执行任务了
            //而且当前线程没有中断,满足这两个条件,线程中断
            if ((runStateAtLeast(ctl.get(), STOP) ||
                 (Thread.interrupted() &&
                  runStateAtLeast(ctl.get(), STOP))) &&
                !wt.isInterrupted())
                wt.interrupt();
            try {
               //上面的校验主要是,预防再执行任务的时候判断线程是否被中断了,比如说
               //shutdownnow 就会中断线程
               //钩子方法
                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为空,方便下次循环来队列拿任务
                task = null;
                //该线程执行的任务++
                w.completedTasks++;
                //解锁
                w.unlock();
            }
        }
        //什么时候 这个会是false ,当获取任务为空的时候这个会是false
        //当发生异常的时候 就走不到这里  这个值就是 true
        completedAbruptly = false;
    } finally {
       //说明这个线程结束了,线程结束需要处理一些逻辑
       //completedAbruptly  通过这个字段可以看出,线程为什么结束
       //1.队列拿不到任务(false) 2.发生异常 (true)
        processWorkerExit(w, completedAbruptly);
    }
}

runWorker 主要是再线程中不停的循环拿任务执行,拿不到任务 getTask(),线程执行完毕,调用 processWorkerExit 方法

getTask

//这是线程从队列拿任务
private Runnable getTask() {
    boolean timedOut = false; // Did the last poll() time out?
    //for 循环拿任务
    for (;;) {
        int c = ctl.get();
        int rs = runStateOf(c);

        // 什么情况下不能拿任务了
        //1.线程池状态 大于 shutdown 2.队列为空
        //要注意 线程池状态 等于 shutdown 的时候还可以从队列拿任务来执行,知道队列为空
        if (rs >= SHUTDOWN && (rs >= STOP || workQueue.isEmpty())) {
        //不能再拿任务了,需要关闭线程了,线程池数量减一,返回空,线程执行完毕
            decrementWorkerCount();
            return null;
        }

        int wc = workerCountOf(c);

        //allowCoreThreadTimeOut 这个字段如果设置为 true 表示核心线程允许回收
        // time 为 ture ,要么是 allowCoreThreadTimeOut = true ,要么此时 线程池
        //数量大于核心线程
        //这个字段是干嘛的?判断拿拿任务需不需设置超时时间
        boolean timed = allowCoreThreadTimeOut || wc > corePoolSize;
        //如果线程大于最大线程数量 或者 超时了而且允许设置超时
        if ((wc > maximumPoolSize || (timed && timedOut))
            && (wc > 1 || workQueue.isEmpty())) {
            //减少工作线程,返回空
            if (compareAndDecrementWorkerCount(c))
                return null;
            continue;
        }

        try {
        //是否需要超时控制,如果需要就用poll 超时返回null
            Runnable r = timed ?
                workQueue.poll(keepAliveTime, TimeUnit.NANOSECONDS) :
                workQueue.take();
            if (r != null)
                return r;
            timedOut = true;
        } catch (InterruptedException retry) {
            timedOut = false;
        }
    }
}

processWorkerExit

//线程退出后需要执行的操作
private void processWorkerExit(Worker w, boolean completedAbruptly) {
//completedAbruptly = true 说明发生异常了
    if (completedAbruptly) // If abrupt, then workerCount wasn't adjusted
    //所以需要减少线程数量,不然再gettask 方法就会减少线程数量
        decrementWorkerCount();

    final ReentrantLock mainLock = this.mainLock;
    mainLock.lock();
    try {
    //全局的线程完成任务统计
        completedTaskCount += w.completedTasks;
     //移除线程   
        workers.remove(w);
    } finally {
        mainLock.unlock();
    }

    tryTerminate();

    int c = ctl.get();
    //当前状态小于 stop 也就是 runing 或者 shutdown
    if (runStateLessThan(c, STOP)) {
    //completedAbruptly = false 说明获取任务为空
        if (!completedAbruptly) {
            int min = allowCoreThreadTimeOut ? 0 : corePoolSize;
            if (min == 0 && ! workQueue.isEmpty())
                min = 1;
                //如果获取任务为空,那就是正常退出的,如果当前线程数量大于等于最小值
                //那就不需要重新新建线程了
            if (workerCountOf(c) >= min)
                return; // replacement not needed
        }
        //添加新线程
        //1.发生异常,会新建线程执行任务
        //2.获取任务为空,但是当前线程数量小于最小值,就新建线程
        addWorker(null, false);
    }
}