Java并发编程初识-ThreadPoolExecutor源码浅析| 8月更文挑战

215 阅读8分钟

1. ThreadPoolExecutor 类图

ThreadPoolExecutor类图

Java 中线程池都是基于 ThreadPoolExecutor 实现的

2. ThreadPoolExecutor 类核心属性

public class ThreadPoolExecutor extends AbstractExecutorService {
    
    // 线程池属性值,高3位表示运行状态,低29位表示工作线程数
    // 初始化运行状态为 RUNNING ,工作线程数为0
    private final AtomicInteger ctl = new AtomicInteger(ctlOf(RUNNING, 0));
    
    private static final int COUNT_BITS = Integer.SIZE - 3;
    private static final int CAPACITY   = (1 << COUNT_BITS) - 1;
    
    // 任务队列
    private final BlockingQueue<Runnable> workQueue;

    // 全局锁
    private final ReentrantLock mainLock = new ReentrantLock();

    // 工作线程集合
    private final HashSet<Worker> workers = new HashSet<Worker>();

    // 线程池的终止条件
    private final Condition termination = mainLock.newCondition();

    // 线程池中曾经最大的线程数
    private int largestPoolSize;

    // 线程池任务完成计数器
    private long completedTaskCount;

    // 线程工厂
    private volatile ThreadFactory threadFactory;

    // 拒绝策略,任务队列和线程都满时执行的策略
    private volatile RejectedExecutionHandler handler;

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

    // 是否允许核心线程超时销毁
    private volatile boolean allowCoreThreadTimeOut;

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

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

    // 默认拒绝策略为 AbortPolicy
    private static final RejectedExecutionHandler defaultHandler =
        new AbortPolicy();

    // 获取运行状态
    private static int runStateOf(int c)     { return c & ~CAPACITY; }
  
    // 获取工作线程数
    private static int workerCountOf(int c)  { return c & CAPACITY; }
  
    // 获取 ctl 的 int 类型的数值
    private static int ctlOf(int rs, int wc) { return rs | wc; }
    
    // ......
}

2.1 线程池的运行状态

状态描述
RUNNING正常状态,允许新任务加入,正常处理任务队列中的任务
SHUTDOWN关闭状态,不允许新任务加入,正常处理任务队列中的任务
STOP停止状态,不允许新任务加入,不处理任务队列中的任务,中断执行中的任务
TIDYING整理状态,所有任务结束,工作线程数为0,准备执行 terminated() 方法
TERMINATED终止状态,terminated() 方法执行完成,线程池销毁

2.2 拒绝策略

  • AbortPolicy:直接抛出异常
  • CallerRunsPolicy:只有调用者所在线程来执行任务
  • DiscardOldestPolicy:丢弃任务队列最近一个待执行任务,然后调用 execute() 方法处理任务
  • DiscardPolicy:不处理,丢弃任务

3. Worker 工作线程类(内部类)

private final class Worker
    extends AbstractQueuedSynchronizer
    implements Runnable
{
    // ......
  
    // 执行任务的线程
    final Thread thread;
    
    // 线程创建时执行的初始任务,可能为 null
    Runnable firstTask;
    
    // 线程任务完成计数器
    volatile long completedTasks;

    Worker(Runnable firstTask) {
        // 设置同步状态为-1
        // 避免执行 runWorker() 方法前被中断
        setState(-1);
        this.firstTask = firstTask;
        this.thread = getThreadFactory().newThread(this);
    }

    // 委托给外部类(ThreadPoolExecutor)的 runWorker() 方法执行当前线程的任务
    public void run() {
        runWorker(this);
    }

    // ......
}

Worker 内部类继承了 AbstractQueuedSynchronizer 类实现了互斥锁,主要是为了执行中的任务不被 ThreadPoolExecutor 中断,保证任务正常执行完成

4. 构造方法

public ThreadPoolExecutor(int corePoolSize,
                          int maximumPoolSize,
                          long keepAliveTime,
                          TimeUnit unit,
                          BlockingQueue<Runnable> workQueue,
                          ThreadFactory threadFactory,
                          RejectedExecutionHandler handler) {
    // ......
}
  • corePoolSize:核心线程数

  • maximumPoolSize:最大线程数,如果线程池使用了无界的任务队列,该参数失效

  • keepAliveTime:线程存活时间,工作线程空闲(任务队列无任务可获取)时,保持存活的时间

  • unit:线程存活时间的单位

  • workQueue:任务队列,保存等待执行的任务的阻塞队列

  • threadFactory:创建线程的工厂

  • handler:拒绝策略,当线程和任务队列都满时需要采取一种策略处理提交的任务

5. 提交任务

5.1 execute 提交任务

public void execute(Runnable command) {
    if (command == null)
        throw new NullPointerException();
    int c = ctl.get();
    if (workerCountOf(c) < corePoolSize) {
        // 如果工作线程数小于核心线程数
        // 则创建线程执行任务
        if (addWorker(command, true))
            return;
        c = ctl.get();
    }
    // 工作线程数小于核心线程数时
    // 如果线程池是正常运行状态,添加任务到任务队列
    if (isRunning(c) && workQueue.offer(command)) {
        int recheck = ctl.get();
        // 双重检查,原因:
        //     1. 任务添加到任务队列的过程中,工作线程销毁了
        //     2. 任务添加到任务队列的过程中,线程池被关闭了
        if (! isRunning(recheck) && remove(command))
            // 双重检查不通过,移除任务后,调用拒绝任务方法
            reject(command);
        else if (workerCountOf(recheck) == 0)
            // 如果工作线程数为0则创建线程
            // 执行到该处,任务还在任务队列中,因此工作线程数为0的情况下需要创建线程
            addWorker(null, false);
    }
    // 任务队列满了,创建非核心线程
    else if (!addWorker(command, false))
        // 创建非核心线程失败,调用拒绝任务方法
        reject(command);
}

5.2 addWorker 添加线程

private boolean addWorker(Runnable firstTask, boolean core) {
    retry:
    for (;;) {
        int c = ctl.get();
        int rs = runStateOf(c);

        if (rs >= SHUTDOWN &&
            ! (rs == SHUTDOWN &&
               firstTask == null &&
               ! workQueue.isEmpty()))
            // 1. rs > SHUTDOWN 时,线程池为 STOP、TIDYING、TERMINATED 状态,不允许创建线程,返回 false
            // 2. rs >= SHUTDOWN && firstTask != null 时,线程池为 SHUTDOWN、STOP、TIDYING、TERMINATED 状态,不允许添加任务,返回 false
            // 3. rs >= SHUTDOWN && workQueue.isEmpty() 时,线程池为 SHUTDOWN、STOP、TIDYING、TERMINATED 状态且任务列表为空,不需要创建线程,返回 false
            return false;

        for (;;) {
            int wc = workerCountOf(c);
            if (wc >= CAPACITY ||
                wc >= (core ? corePoolSize : maximumPoolSize))
                // 1. 如果工作线程数大于等于最大线程容量,返回 false
                // 2. 创建核心线程时,如果工作线程数大于等于核心线程数,返回 false
                // 3. 创建非核心线程时,如果工作线程数大于等于最大线程数,返回 false
                return false;
            if (compareAndIncrementWorkerCount(c))
                // CAS 添加工作线程数失败,重新执行 addWorker() 方法
                break retry;
            c = ctl.get();
            if (runStateOf(c) != rs)
                // 线程池状态发生变化,重新执行 addWorker() 方法
                continue retry;
        }
    }

    boolean workerStarted = false;
    boolean workerAdded = false;
    Worker w = null;
    try {
        // 新建工作线程并指定初始任务
        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());
				        // 再次检查线程池运行状态
              	// 1. 如果是 RUNNING 状态,则继续创建线程
                // 2. 如果是 SHUTDOWN 状态且初始任务为空,则继续创建线程
                if (rs < SHUTDOWN ||
                    (rs == SHUTDOWN && firstTask == null)) {
                    // 预先检查线程是否可启动
                    if (t.isAlive())
                        throw new IllegalThreadStateException();
                    // 添加线程到工作线程集合
                    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)
            // 工作线程启动失败时
            // 1. 移除线程
            // 2. 工作线程数减1
            // 3. 尝试终止线程池
            addWorkerFailed(w);
    }
    return workerStarted;
}

6. 任务的执行

6.1 runWorker 工作线程执行

final void runWorker(Worker w) {
    Thread wt = Thread.currentThread();
    Runnable task = w.firstTask;
    w.firstTask = null;
    // 调用释放锁方法,允许中断线程
    w.unlock();
    // 工作线程是否异常结束
    boolean completedAbruptly = true;
    try {
        // 从任务队列循环获取任务执行
        while (task != null || (task = getTask()) != null) {
            // 获取锁,避免执行任务过程中被中断
            w.lock();
            // 1. 如果线程池是 STOP、TIDYING、TERMINATED 状态,且当前工作线程未标记中断,则需要标记中断
            // 2. 如果线程池是 RUNNING、SHUTDOWN 状态,且当前工作线程已标记中断,则需要取消标记中断
            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;
                // 计数器加1
                w.completedTasks++;
                // 释放锁
                w.unlock();
            }
        }
        completedAbruptly = false;
    } finally {
        // 将工作线程移除
        processWorkerExit(w, completedAbruptly);
    }
}

6.2 getTask 获取任务

private Runnable getTask() {
    // 判断是否已执行超时获取任务
    boolean timedOut = false;

    // 循环执行获取任务逻辑
    for (;;) {
        int c = ctl.get();
        int rs = runStateOf(c);

        // 下列情况下减少工作线程数,获取任务为空:
        //     1. 线程池状态为 STOP、TIDYING、TERMINATED
        //     2. 线程池状态为 SHUTDOWN 并且任务队列为空
        if (rs >= SHUTDOWN && (rs >= STOP || workQueue.isEmpty())) {
            decrementWorkerCount();
            return null;
        }

        int wc = workerCountOf(c);

        // 工作线程获取任务的方式:
        //     1. 超时获取
        //     2. 阻塞获取
        // 超时获取任务的依据:
        //     1. 允许任何线程都超时获取
        //     2. 工作线程数大于设置的核心线程数
        boolean timed = allowCoreThreadTimeOut || wc > corePoolSize;

        // 下列情况下减少工作线程数,获取任务为空:
        //     1. 工作线程数大于1且大于最大线程数(最大线程数可以由 setMaximumPoolSize 方法更改)
        //     2. 工作线程数大于最大线程数且任务队列为空
        //     3. 已超时获取任务且工作线程数大于1
        //     4. 已超时获取任务且任务队列为空
        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;
        }
    }
}

6.3 processWorkerExit 移除工作线程

private void processWorkerExit(Worker w, boolean completedAbruptly) {
    // 如果工作线程是非正常退出循环获取任务逻辑
    // 那么工作线程数还未减少,需要执行减少
    if (completedAbruptly)
        decrementWorkerCount();

    final ReentrantLock mainLock = this.mainLock;
    // 获取全局锁
    mainLock.lock();
    try {
        // 移除工作线程时,将该线程已完成的任务数添加进线程池完成的任务数
        completedTaskCount += w.completedTasks;
        // 工作线程集合中移除该线程
        workers.remove(w);
    } finally {
        // 释放全局锁
        mainLock.unlock();
    }

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

    int c = ctl.get();
    // 如果线程池状态为 RUNNING、SHUTDOWN
    if (runStateLessThan(c, STOP)) {
        // 如果线程是正常退出
        if (!completedAbruptly) {
            // 计算出线程池需要保持的最小线程数
            int min = allowCoreThreadTimeOut ? 0 : corePoolSize;
            if (min == 0 && ! workQueue.isEmpty())
                min = 1;
            // 工作线程数大于等于需要保持的最小线程数,退出不需要新增线程
            if (workerCountOf(c) >= min)
                return;
        }
        // 新增一个未指定初始任务的非核心工作线程
        // 新增的原因:
        //     1. 当前工作线程非正常退出,需要换个新的线程
        //     2. 线程池的工作线程数小于需要保持的最小线程数,需要添加个线程
        addWorker(null, false);
    }
}

7. 关闭线程池

7.1 shutdown 关闭线程池(友好式)

不允许新任务加入,正常处理任务队列中的任务

public void shutdown() {
    final ReentrantLock mainLock = this.mainLock;
    // 获取全局锁
    mainLock.lock();
    try {
        // 检查是否有关闭线程池的权限
        checkShutdownAccess();
        // 设置线程池状态为 SHUTDOWN
        advanceRunState(SHUTDOWN);
        // 尝试中断工作线程
        interruptIdleWorkers();
        // 回调线程池关闭方法,JDK 为 ScheduledThreadPoolExecutor 提供的
        onShutdown();
    } finally {
        // 释放全局锁
        mainLock.unlock();
    }
    // 尝试终止线程池
    tryTerminate();
}

7.2 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;
}

7.3 tryTerminate 尝试终止线程池

final void tryTerminate() {
    for (;;) {
        int c = ctl.get();
        // 下列情况直接退出终止线程池:
        //     1. 线程池状态为 RUNNING
        //     2. 线程池状态为 TIDYING、TERMINATED
        //     3. 线程池状态为 SHUTDOWN 且任务列表不为空
        if (isRunning(c) ||
            runStateAtLeast(c, TIDYING) ||
            (runStateOf(c) == SHUTDOWN && ! workQueue.isEmpty()))
            return;
        // 当工作线程数不为0,只有尝试终止一个工作线程的资格
        if (workerCountOf(c) != 0) {
            interruptIdleWorkers(ONLY_ONE);
            return;
        }

        final ReentrantLock mainLock = this.mainLock;
        // 获取全局锁
        mainLock.lock();
        try {
            // 设置线程池状态为 TIDYING 和工作线程数为0
            if (ctl.compareAndSet(c, ctlOf(TIDYING, 0))) {
                try {
                    // 调用终止方法
                    terminated();
                } finally {
                    // 设置线程池状态为 TERMINATED 和工作线程数为0
                    ctl.set(ctlOf(TERMINATED, 0));
                    // 唤醒所有等待线程终止条件的线程
                    termination.signalAll();
                }
                return;
            }
        } finally {
            // 释放全局锁
            mainLock.unlock();
        }
    }
}

满足下列条件时才能进一步终止线程池:

  • 线程池状态为 SHUTDOWN 时,工作线程数为0,任务队列为空
  • 线程池状态为 STOP 时,工作线程数为0