线程池源码解析

182 阅读6分钟

execute

public void execute(Runnable command) {

    //(1) 如果任务为null,则抛出NPE异常
    if (command == null)
        throw new NullPointerException();

    //(2)获取当前线程池的状态+线程个数变量的组合值
    int c = ctl.get();

    //(3)当前线程池线程个数是否小于corePoolSize,小于则开启新线程运行
    if (workerCountOf(c) < corePoolSize) {
        if (addWorker(command, true))
            return;
        c = ctl.get();
    }

    //(4)如果线程池处于RUNNING状态,则添加任务到阻塞队列
    if (isRunning(c) && workQueue.offer(command)) {

        //(4.1)二次检查
        int recheck = ctl.get();
        //(4.2)如果当前线程池状态不是RUNNING则从队列删除任务,并执行拒绝策略
        if (! isRunning(recheck) && remove(command))
            reject(command);

        //(4.3)否者如果当前线程池线程空,则添加一个线程
        else if (workerCountOf(recheck) == 0)
            addWorker(null, false);
    }
    //(5)如果队列满了,则新增线程,新增失败则执行拒绝策略
    else if (!addWorker(command, false))
        reject(command);
}

addWorker

private boolean addWorker(Runnable firstTask, boolean core) {
    retry:
    for (;;) {

        int c = ctl.get();
        //  获取运行状态
        int rs = runStateOf(c);

        // Check if queue empty only if necessary.
        // 如果状态值 >= SHUTDOWN (不接新任务&不处理队列任务)
        // 并且 如果 !(rs为SHUTDOWN 且 firsTask为空 且 阻塞队列不为空)
        if (rs >= SHUTDOWN &&
            ! (rs == SHUTDOWN &&
               firstTask == null &&
               ! workQueue.isEmpty()))
            // 返回false
            return false;

        for (;;) {
            //获取线程数wc
            int wc = workerCountOf(c);
            // 如果wc大与容量 || core如果为true表示根据corePoolSize来比较,否则为maximumPoolSize
            if (wc >= CAPACITY ||
                wc >= (core ? corePoolSize : maximumPoolSize))
                return false;
            // 增加workerCount(原子操作)
            if (compareAndIncrementWorkerCount(c))
                // 如果增加成功,则跳出
                break retry;
            // wc增加失败,则再次获取runState
            c = ctl.get();  // Re-read ctl
            // 如果当前的运行状态不等于rs,说明状态已被改变,返回重新执行
            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 {
        // 根据firstTask来创建Worker对象
        w = new Worker(firstTask);
        // 根据worker创建一个线程
        final Thread t = w.thread;
        if (t != null) {
            // new一个锁
            final ReentrantLock mainLock = this.mainLock;
            // 加锁
            mainLock.lock();
            try {
                // Recheck while holding lock.
                // Back out on ThreadFactory failure or if
                // shut down before lock acquired.
                // 获取runState
                int rs = runStateOf(ctl.get());
                // 如果rs小于SHUTDOWN(处于运行)或者(rs=SHUTDOWN && firstTask == null)
                // firstTask == null证明只新建线程而不执行任务
                if (rs < SHUTDOWN ||
                    (rs == SHUTDOWN && firstTask == null)) {
                    // 如果t活着就抛异常
                    if (t.isAlive()) // precheck that t is startable
                        throw new IllegalThreadStateException();
                    // 否则加入worker(HashSet)
                    //workers包含池中的所有工作线程。仅在持有mainLock时访问。
                    workers.add(w);
                    // 获取工作线程数量
                    int s = workers.size();
                    //largestPoolSize记录着线程池中出现过的最大线程数量
                    if (s > largestPoolSize)
                        // 如果 s比它还要大,则将s赋值给它
                        largestPoolSize = s;
                    // worker的添加工作状态改为true
                    workerAdded = true;
                }
            } finally {
                mainLock.unlock();
            }
            // 如果worker的添加工作完成
            if (workerAdded) {
                // 启动线程
                t.start();
                // 修改线程启动状态
                workerStarted = true;
            }
        }
    } finally {
        if (! workerStarted)
            addWorkerFailed(w);
    }
    // 返回线启动状态
    return workerStarted;

runWorker

final void runWorker(Worker w) {
    // 拿到当前线程
    Thread wt = Thread.currentThread();
    // 拿到当前任务
    Runnable task = w.firstTask;
    // 将Worker.firstTask置空 并且释放锁
    w.firstTask = null;
    w.unlock(); // allow interrupts
    boolean completedAbruptly = true;
    try {
        // 如果task或者getTask不为空,则一直循环
        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
            //  return ctl.get() >= stop
            // 如果线程池状态>=STOP 或者 (线程中断且线程池状态>=STOP)且当前线程没有中断
            // 其实就是保证两点:
            // 1. 线程池没有停止
            // 2. 保证线程没有中断
            if ((runStateAtLeast(ctl.get(), STOP) ||
                 (Thread.interrupted() &&
                  runStateAtLeast(ctl.get(), STOP))) &&
                !wt.isInterrupted())
                // 中断当前线程
                wt.interrupt();
            try {
                // 空方法
                beforeExecute(wt, task);
                Throwable thrown = null;
                try {
                    // 执行run方法(Runable对象)
                    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();
            }
        }
        completedAbruptly = false;
    } finally {
        // 退出工作
        processWorkerExit(w, completedAbruptly);
    }

getTask

 1 /**
 2  * ThreadPoolExecutor:
 3  */
 4 private Runnable getTask() {
 5     //timedOut标志位用来判断poll方法拿取任务是否超时了
 6     boolean timedOut = false;
 7 
 8     for (; ; ) {
 9         int c = ctl.get();
10         //重新获取当前线程池的运行状态
11         int rs = runStateOf(c);
12 
13         /*
14         如果当前线程池是SHUTDOWN状态,并且阻塞队列为空的时候;或者当前线程池的状态大于等于STOP
15         以上两种情况都会将工作线程-1,直接返回null。因为这两种情况下不需要
16         获取任务了。工作线程-1后,后续会在processWorkerExit方法中从workers集合中剔除掉这个Worker等待GC的
17          */
18         if (rs >= SHUTDOWN && (rs >= STOP || workQueue.isEmpty())) {
19             decrementWorkerCount();
20             return null;
21         }
22
23         /*
24         走到这里说明当前线程池要么是RUNNING状态,要么是SHUTDOWN状态但是阻塞队列不为空(SHUTDOWN状态还是要
25         处理阻塞队列中的任务的)
26 
27         重新获取当前线程池的工作线程数
28          */
29         int wc = workerCountOf(c);
30 
31         /*
32         timed标志位表示工作线程是否需要超时销毁
33         如果allowCoreThreadTimeOut设置为true(表示空闲的核心线程也是要超时销毁的),或者当前线程数大于
34         核心线程数(这个条件代表的是空闲的非核心线程是要被销毁的,如果allowCoreThreadTimeOut为false,
35         那么线程池中最多保留“传进线程池中的核心线程数”个线程),就将timed置为true
36          */
37         boolean timed = allowCoreThreadTimeOut || wc > corePoolSize;
38
39         /*
40         如果当前工作线程数大于最大线程数,可能是调用了setMaximumPoolSize方法,把最大线程数改小了(走到这里
41         说明addWorker方法运行成功,而在addWorker方法中的第34行代码处已经判断了大于最大线程数的情况);
42         timedOut为true说明当前已经不是第一次循环了,在上次循环中已经发生了poll的超时。所以总结来说这个if条件的意思是:
43         <1.1>如果当前工作线程数大于最大线程数
44         <1.2>或者当前线程处于空闲状态并且是需要被销毁的
45         <2.1>并且当前工作线程要有多于一个
46         <2.2>或者当前阻塞队列是空的
47         满足上面两个条件,就将工作线程-1,去掉当前这个多余的线程,然后直接返回
48          */
49         if ((wc > maximumPoolSize || (timed && timedOut))
50                 && (wc > 1 || workQueue.isEmpty())) {
51             //这里的方法和decrementWorkerCount方法的区别是不会死循环去一直CAS尝试,如果失败了就直接返回false
52             if (compareAndDecrementWorkerCount(c))
53                 return null;
54             //如果CAS-1失败了,就进入到下次循环中继续判断即可
55             continue;
56         }
57
58         try {
59             /*
60             如果timed为true,则通过poll方法进行限时拿取(超过keepAliveTime时间没有拿取到,就直接返回null),
61             否则通过take方法进行拿取(如果阻塞队列为空,take方法在此时就会被阻塞住,也就是本线程会被阻塞住,直到
62             阻塞队列中有数据了。也就是说如果timed为false的话,这些工作线程会一直被阻塞在这里)
63              */
64             Runnable r = timed ?
65                     workQueue.poll(keepAliveTime, TimeUnit.NANOSECONDS) :
66                     workQueue.take();
67             if (r != null)
68                 //如果拿取到任务了,就直接返回给Worker处理
69                 return r;
70             /*
71             走到这里说明发生了poll超时,那么将timedOut标志位置为true,进入到下一次循环中重试
72             (大概率会走到第53行代码处返回null)
73              */
74             timedOut = true;
75         } catch (InterruptedException retry) {
76             //如果在阻塞的过程中发生了中断,那么将timedOut置为false,也进入到下一次循环中重试
77             timedOut = false;
78         }
79     }
80     /*
81     以上的逻辑说明了:核心线程和非核心线程的区别并不是在Worker中有个表示是否是核心线程的属性,Worker是无状态的,
82     每个Worker都是一样的。而区分是通过判断当前工作线程数是否大于核心线程数来进行的(因为只有阻塞队列满了的时候
83     才会去创建新的非核心线程,也就会使工作线程数大于核心线程数)。如果大于,那么不管之前这个线程到底是核心线程
84     还是非核心线程,现在我就认定当前这个线程就是“非核心线程“,那么等这个“非核心线程”空闲时间超过keepAliveTime后,
85     就会被销毁
86      */
87 }

参考: