ThreadPoolExecutor源码分析

在分析ThreadPoolExecutor线程池之前, 需要先对对线程池的状态与线程的数量进行了解

// 记录线程池状态和线程数量(总共32位,前3位表示线程池状态,后29位表示线程数量)
private final AtomicInteger ctl = new AtomicInteger(ctlOf(RUNNING, 0));
// 线程数量统计位数29  Integer.SIZE=32 
private static final int COUNT_BITS = Integer.SIZE - 3;

/*
   容量:
   1的二进制:      0000 0000 0000 0000 0000 0000 0000 0001
   向左移动29位:   0010 0000 0000 0000 0000 0000 0000 0000
   减1等到:       0001 1111 1111 1111 1111 1111 1111 1111 
*/
private static final int CAPACITY   = (1 << COUNT_BITS) - 1;

/*
    运行状态:
    -1的二进制:    1000 0000 0000 0000 0000 0000 0000 0001
    反码:         0111 1111 1111 1111 1111 1111 1111 1110
    补码:         0111 1111 1111 1111 1111 1111 1111 1111
    向左移动29位:  1110 0000 0000 0000 0000 0000 0001
*/
private static final int RUNNING    = -1 << COUNT_BITS;
/*
    关闭状态: 拒绝新任务但是处理阻塞队列里的任务
    0的二进制:    0000 0000 0000 0000 0000 0000 0000 0000
    向左移动29位:  0000 0000 0000 0000 0000 0000 0000
*/
private static final int SHUTDOWN   =  0 << COUNT_BITS;
/*
    停止状态: 拒绝新任务并且抛弃阻塞队列里的任务同时会中断正在处理的任务
    0的二进制:    0000 0000 0000 0000 0000 0000 0000 0001
    向左移动29位:  0010 0000 0000 0000 0000 0000 0000
*/  
private static final int STOP       =  1 << COUNT_BITS; 
/*
    整理状态: 所有任务都执行完(包含阻塞队列里面任务)当前线程池活动,线程为0,将要调用terminated方法
    0的二进制:    0000 0000 0000 0000 0000 0000 0000 0010
    向左移动29位:  0100 0000 0000 0000 0000 0000 0000
*/   
private static final int TIDYING    =  2 << COUNT_BITS;
/*
    终止状态:  terminated方法调用完成以后的状态法
    0的二进制:    0000 0000 0000 0000 0000 0000 0000 0011
    向左移动29位:  0110 0000 0000 0000 0000 0000 0000
*/ 
private static final int TERMINATED =  3 << COUNT_BITS;

// 获取运行状态(获取前3位)
private static int runStateOf(int c)     { return c & ~CAPACITY; }
// 获取线程个数(获取后29位)
private static int workerCountOf(int c)  { return c & CAPACITY; }
private static int ctlOf(int rs, int wc) { return rs | wc; }


//用于存放线程任务的阻塞队列
private final BlockingQueue workQueue;

//重入锁
private final ReentrantLock mainLock = new ReentrantLock();

//线程池当中的线程集合,只有当拥有mainLock锁的时候,才可以进行访问
private final HashSet workers = new HashSet();

//等待条件支持终止
private final Condition termination = mainLock.newCondition();

//创建新线程的线程工厂
private volatile ThreadFactory threadFactory;

//饱和策略
private volatile RejectedExecutionHandler handler;

二进制位运算总结
正数的原码、反码、补码都一样;
负数的反码 = 原码的符号位不变,其他位取反;
负数的补码 = 反码+1;
0的原码、反码、补码都是0;
计算机以补码进行运算;
取反不同于反码;

线程池创建时, 线程的状态为运作中, 线程的数量为0

private final AtomicInteger ctl = new AtomicInteger(ctlOf(RUNNING, 0));

execute执行流程.png

我们先来分析一下execute 操作

 public void execute(Runnable command) {
        if (command == null)
            throw new NullPointerException();
        // 获取线程池状态和线程数量
        int c = ctl.get();
        // 判断线程个数与核心线程数 ,小于这执行addWorker(com, true)方法
        if (workerCountOf(c) < corePoolSize) {  
            if (addWorker(command, true))
                return;
            c = ctl.get();
        }
        // 如果线程池处于RUNNING状态,则添加任务到阻塞队列
        if (isRunning(c) && workQueue.offer(command)) {
                // 二次检查
                int recheck = ctl.get();
                //  如果线程池不处于RUNNING状态 , 从队列中删除
                if (! isRunning(recheck) && remove(command))
                 //执行处理策略
                reject(command);
                // 如果当前线程池数量为空, 执行addWorker(null, false)方法 
                else if (workerCountOf(recheck) == 0)
                addWorker(null, false);
        }
        // 执行addWorker(com, false)
        else if (!addWorker(command, false))
            reject(command);
    }

看完上面源码,其中有三个地方执行了 addWorker 方法, 且参数不一样, 下面对addWorker源码分析

 private boolean addWorker(Runnable firstTask, boolean core) {
        retry:
        for (;;) {
            int c = ctl.get();
            // 获状线程状态
            int rs = runStateOf(c);
            // 线程不处于运行中 &&  ! (关闭 && 任务为空 && 队列不为空)返回false
            if (rs >= SHUTDOWN &&
                ! (rs == SHUTDOWN &&
                   firstTask == null &&
                   ! workQueue.isEmpty()))
                return false;
            // 线程运行 或者 线程关闭任务不为空或者队列不为空往下运行
            for (;;) {
                // 获取线程个数
                int wc = workerCountOf(c);
                // 线程数大于容量数 || 线程数大于核心/最大线程数, 返回false
                if (wc >= CAPACITY ||
                   // core如果为true, 线程数与线程池核心线程数比较,false, 线程数与线程池最大线程数比较
                    wc >= (core ? corePoolSize : maximumPoolSize))
                    return false;
                // 比较与替换线程数 + 1, 成功->循环, 失败->重新执行这个循环
                if (compareAndIncrementWorkerCount(c))
                    break retry;
                c = ctl.get();  // Re-read ctl
                if (runStateOf(c) != rs)
                    continue retry;
            }
        }
        boolean workerStarted = false;
        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 {
                    // 再次获取线程状态
                    int rs = runStateOf(ctl.get());
                    // 线程运行中 || (线程关闭 &&  任务为空)
                    if (rs < SHUTDOWN ||
                        (rs == SHUTDOWN && firstTask == null)) {
                        // 若创建的Thread是活动的抛异常
                        if (t.isAlive()) 
                            throw new IllegalThreadStateException();
                        // 下面的操作是将Worker加入列表中, 执行, 执行完毕删除
                        workers.add(w);
                        int s = workers.size();
                        if (s > largestPoolSize)
                            largestPoolSize = s;
                        workerAdded = true;
                    }
                } finally {
                    mainLock.unlock();
                }
                if (workerAdded) {
                   // 线程启动,执行任务(Worker.thread(firstTask).start())
                   // 找到Worker的实现的run方法
                    t.start();
                    workerStarted = true;
                }
            }
        } finally {
            // 若执行失败, 清理工作
            if (! workerStarted)
                addWorkerFailed(w);
        }
        return workerStarted;
    }

addWorker方法可以拆分为两个阶段
阶段一: 使用循环 + CAS增加线程数
阶段二: 加锁,创建Worker,然后执行任务

下面分析Worker对象

 private final class Worker
        extends AbstractQueuedSynchronizer
        implements Runnable
    {
        private static final long serialVersionUID = 6138294804551838833L;
        // 线程工厂生成的线程, 创建ThreadPoolExecutor指定工厂
        final Thread thread;
        // 要运行的初始任务
        Runnable firstTask;
        // 统计执行了多少个线程
        volatile long completedTasks;

        Worker(Runnable firstTask) {
            setState(-1); // inhibit interrupts until runWorker
            this.firstTask = firstTask;
            this.thread = getThreadFactory().newThread(this);
        }

addWorder方法中执行 t.start();方法, 实际是在运行Worder中的run方法

public void run() {
            runWorker(this);
}
final void runWorker(Worker w) {
        Thread wt = Thread.currentThread();
        Runnable task = w.firstTask;
        w.firstTask = null;
        w.unlock(); // 释放锁, 允许中断
        boolean completedAbruptly = true;
        try {
          // 先执行firstTask,再从workerQueue中取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
                if ((runStateAtLeast(ctl.get(), STOP) ||
                     (Thread.interrupted() &&
                      runStateAtLeast(ctl.get(), STOP))) &&
                    !wt.isInterrupted())
                    wt.interrupt();
                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++;
                    w.unlock();
                }
            }
            completedAbruptly = false;
        } finally {
            // 处理并退出当前worker
            processWorkerExit(w, completedAbruptly);
        }
    }

runWorker主要分为几步

  1. 拿到任务 : getTask
  2. 加锁执行任务
  3. 执行完毕之后做善后工作 : processWorkerExit

getTask方法

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

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

            // Check if queue empty only if necessary.
            if (rs >= SHUTDOWN && (rs >= STOP || workQueue.isEmpty())) {
                decrementWorkerCount();
                return null;
            }

            int wc = workerCountOf(c);

            // 此处决定是否销毁线程, 条件是开启了 allowCoreThreadTimeOut,或者总线程数大于了核心线程数
            boolean timed = allowCoreThreadTimeOut || wc > corePoolSize;

            if ((wc > maximumPoolSize || (timed && timedOut))
                && (wc > 1 || workQueue.isEmpty())) {
                if (compareAndDecrementWorkerCount(c))
                    return null;
                continue;
            }

            try {
                Runnable r = timed ?
                    workQueue.poll(keepAliveTime, TimeUnit.NANOSECONDS) : // 使用超时移除
                    workQueue.take(); // 使用阻塞移除
                if (r != null)
                    return r;
                timedOut = true;
            } catch (InterruptedException retry) {
                timedOut = false;
            }
        }
    }

如果设置了allowCoreThreadTimeOut(true) 或者当前运行的任务数大于设置的核心线程数,那么timed =true .此时将使用workQueue.poll(keepAliveTime, TimeUnit.NANOSECONDS)从任务队列中取任务,而如果没有设置,那么使用workQueue.take() 取任务,对于阻塞队列,poll(long timeout, TimeUnit unit) 将会在规定的时间内去任务, 如果没取到就返回null, take()会一直阻塞,等待任务的添加. 这里就是为什么核心线程数可以一直存在, 不被销毁的原因

processWorkerExit 方法

private void processWorkerExit(Worker w, boolean completedAbruptly) {
        if (completedAbruptly) // 如果是突然完成,需要通过CAS操作,workerCount-1
            decrementWorkerCount();

        final ReentrantLock mainLock = this.mainLock;
        mainLock.lock();
        try {
            // 线程池统计的完成任务数completedTaskCount加上worker当中完成的任务数
            completedTaskCount += w.completedTasks;
            workers.remove(w);// 从线程集合移除
        } finally {
            mainLock.unlock();
        }

        // 尝试终止线程池
        tryTerminate();

        int c = ctl.get();
        if (runStateLessThan(c, STOP)) {
            if (!completedAbruptly) {
                int min = allowCoreThreadTimeOut ? 0 : corePoolSize;
                if (min == 0 && ! workQueue.isEmpty())
                    min = 1;
                if (workerCountOf(c) >= min)
                    return; // replacement not needed
            }
            addWorker(null, false);
        }
    }

小结
线程池源码分析的时候, 需要围绕这execute的执行流程阅读, 然后理解ThreadPoolExecutor七大参数在代码中的作用:

  1. corePoolSize: 线程池中的核心线程数
    1.1 判断线程数是否小于核心线程数, 小于则直接创建创建线程并执行工作
    1.2 若线程数小于核心线程数, workQueue.take(), 阻塞, 保证核心线程数一直存活
  2. maximumPoolSize: 最大线程数, 必须大于1
    2.1 判断线程数是否大于最大线程数, 大于则执行拒绝策略
  3. keepAliveTime: 多余的空闲时间
    3.1 若线程数大于核心线程数, workQueue.poll(keepAliveTime, TimeUnit.NANOSECONDS), 超时将多余的线程回收
  4. unit: keepAliveTime单位
    4.1 多余时间单位
  5. queueCapacity: 任务队列
    5.1 任务队列若满, 创建线程去执行任务, 所以需要注意, 队列长度不能设置太长, 若设置太长, 无法创建新的线程执行任务
    5.2 使用阻塞队列的特性, 保证核心线程的存活与多余线程的超时回收
  6. threadFactory: 线程池中线程工厂
    6.1 创建Worker中的Thread的线程工厂, 在开发工厂中, 可以设置为带模块的名字, 方便线程追踪
  7. rejectedExecutionHandler: 拒绝策略

你可能感兴趣的:(ThreadPoolExecutor源码分析)