《别再懵圈!一文读懂线程池源码逻辑》

目录

1.Executor 接口

2.ExecutorService 接口

3.AbstractExecutorService抽象类

4.ThreadPoolExecutor 类

5.接着,详细介绍一下:ThreadPoolExecutor类的关键方法:execute()、addWorker()、runWoker()、runWoker方法的getTask()

①核心入口execute()方法执行逻辑如下:

②addWorker()方法逻辑

③runWorker()方法逻辑

④getTask()方法逻辑:被runWoker()调用

最后梳理一下:

以上内容比较详细的介绍了ThreadPoolExecutor的继承体系,以及相关的核心源码,谢谢您的观看。


《别再懵圈!一文读懂线程池源码逻辑》_第1张图片

这是线程池标准实现类的继承体系图,下面解释梳理一下,相信跟着博主梳理完后对线程池的执行心里面会自然而然形成一个框架,达到这种就算是对于线程池理解可以了,话不多说开始吧。

1.Executor 接口

作用作为线程执行机制的基础抽象,它将任务提交与任务执行进行解耦。只定义了一个 execute(Runnable command) 方法,用于接收一个 Runnable 类型的任务并安排其执行。通过这个接口,开发者可以以统一的方式提交任务,而具体的执行逻辑由实现类来决定,为后续更复杂的线程池实现提供了最基础的规范 。

// 线程执行机制的基础抽象接口,将任务提交与任务执行解耦
public interface Executor {
    // 执行提交的Runnable任务
    // 参数:command - 待执行的任务
    void execute(Runnable command);
}

2.ExecutorService 接口

作用继承自 Executor 接口,在其基础上进行了功能扩展。除了具备 Executor 提交任务执行的能力外,还提供了对线程池生命周期的管理方法,如 shutdown() 用于平滑关闭线程池(不再接受新任务,但会处理完已提交任务) 、shutdownNow() 用于强制关闭线程池(尝试终止正在执行的任务,并返回等待执行的任务列表) ;以及异步任务执行相关方法,像 submit 系列方法可提交任务并获取任务执行结果(通过 Future ),invokeAll 和 invokeAny 等方法可批量执行任务并获取结果等,极大地丰富了线程池的使用场景和功能。

// 继承Executor并扩展,提供线程池生命周期管理和异步任务执行能力
public interface ExecutorService extends Executor {
    
    // 平滑关闭线程池:不再接受新任务,但会处理完已提交的任务
    void shutdown();
    
    // 强制关闭线程池:尝试终止正在执行的任务,返回等待执行的任务列表
    List shutdownNow();
    
    // 判断线程池是否已调用shutdown()
    boolean isShutdown();
    
    // 判断线程池是否已完全终止
    boolean isTerminated();
    
    // 阻塞等待线程池终止,超时后返回结果
    boolean awaitTermination(long timeout, TimeUnit unit) throws InterruptedException;
    
    // 提交Callable任务,返回Future获取结果
     Future submit(Callable task);
    
    // 提交Runnable任务,并指定结果返回值
     Future submit(Runnable task, T result);
    
    // 提交Runnable任务,返回Future用于判断任务是否完成
    Future submit(Runnable task);
    
    // 批量执行Callable任务,返回包含所有任务对应Future的列表
     List> invokeAll(Collection> tasks) throws InterruptedException;
    
    // 批量执行Callable任务,超时后返回已完成任务的结果
     List> invokeAll(Collection> tasks, long timeout, TimeUnit unit) throws InterruptedException;
    
    // 执行一组任务,任一任务成功完成则返回其结果,其他任务终止
     T invokeAny(Collection> tasks) throws InterruptedException, ExecutionException;
    
    // 执行一组任务,任一任务在超时前成功完成则返回其结果
     T invokeAny(Collection> tasks, long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException;
}

3.AbstractExecutorService抽象类

作用实现了 ExecutorService 接口的部分方法,为 ExecutorService 接口提供了一个默认的实现框架。将一些通用的任务提交逻辑进行了抽象实现,例如 submit 方法的默认实现。当开发者自定义线程池类时,如果继承自 AbstractExecutorService ,就可以基于这些默认实现,专注于线程池核心执行逻辑等方面的定制,减少了重复代码编写,提高了开发效率 。

// 为ExecutorService提供默认实现的抽象类
public abstract class AbstractExecutorService implements ExecutorService {
    
    // 创建RunnableFuture对象,用于包装任务
    protected  RunnableFuture newTaskFor(Runnable runnable, T value) {
        return new FutureTask(runnable, value);
    }
    
    // 创建RunnableFuture对象,用于包装任务
    protected  RunnableFuture newTaskFor(Callable callable) {
        return new FutureTask(callable);
    }
    
    // 提交Runnable任务的默认实现
    public Future submit(Runnable task) {
        if (task == null) throw new NullPointerException();
        RunnableFuture ftask = newTaskFor(task, null);
        execute(ftask);
        return ftask;
    }
    
    // 提交Runnable任务并指定结果的默认实现
    public  Future submit(Runnable task, T result) {
        if (task == null) throw new NullPointerException();
        RunnableFuture ftask = newTaskFor(task, result);
        execute(ftask);
        return ftask;
    }
    
    // 提交Callable任务的默认实现
    public  Future submit(Callable task) {
        if (task == null) throw new NullPointerException();
        RunnableFuture ftask = newTaskFor(task);
        execute(ftask);
        return ftask;
    }
    
    // 批量执行任务的默认实现
    private  T doInvokeAny(Collection> tasks, boolean timed, long nanos) throws InterruptedException, ExecutionException, TimeoutException {
        // 实现逻辑省略...
    }
    
    // 其他批量执行方法的实现...
}

4.ThreadPoolExecutor 类

作用是线程池的核心实现类,继承自 AbstractExecutorService 。它负责具体的线程池功能实现,包括线程的创建、管理,任务队列的维护等。通过设置诸如核心线程数(corePoolSize )、最大线程数(maximumPoolSize )、空闲线程存活时间(keepAliveTime )、任务队列(workQueue )等参数,能够灵活地控制线程池的行为,以满足不同的并发场景需求。例如,根据任务量动态调整线程数量,合理利用系统资源,避免线程过多或过少带来的性能问题 。同时采用池化思想管理一定数量的线程来调度执行提交的任务,且定义了一套线程池的生命周期状态,用一个ctl变量来同时保存当前池状态(高3位)和当前池线程数(低29位)。

//导包

public class ThreadPoolExecutor extends AbstractExecutorService {

    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 static final int RUNNING    = -1 << COUNT_BITS;
    private static final int SHUTDOWN   =  0 << COUNT_BITS;
    private static final int STOP       =  1 << COUNT_BITS;
    private static final int TIDYING    =  2 << COUNT_BITS;
    private static final int TERMINATED =  3 << COUNT_BITS;

    private final BlockingQueue workQueue;
    private final ReentrantLock mainLock = new ReentrantLock();
    private final HashSet workers = new HashSet<>();
    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;
    private static final RejectedExecutionHandler defaultHandler = new AbortPolicy();

    // 初始化线程池参数和状态
    public ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue workQueue, ThreadFactory threadFactory, RejectedExecutionHandler handler) { // 方法实现 }

    // 执行提交的任务,根据线程池状态和配置决定如何处理任务
    public void execute(Runnable command) { // 方法实现 }

    // 添加新的工作线程来执行任务
    private boolean addWorker(Runnable firstTask, boolean core) { // 方法实现 }

    // 工作线程的主循环,负责执行任务和获取新任务
    final void runWorker(Worker w) { // 方法实现 }

    // 从任务队列获取待执行的任务,可能阻塞或超时
    private Runnable getTask() { // 方法实现 }

    // 处理工作线程退出逻辑,更新线程池状态
    private void processWorkerExit(Worker w, boolean completedAbruptly) { // 方法实现 }

    // 尝试将线程池转换为终止状态
    final void tryTerminate() { // 方法实现 }

    // 平滑关闭线程池,不再接受新任务但处理完已提交任务
    public void shutdown() { // 方法实现 }

    // 立即关闭线程池,尝试终止所有任务并返回未执行的任务
    public List shutdownNow() { // 方法实现 }

    // 判断线程池是否已调用shutdown()
    public boolean isShutdown() { // 方法实现 }

    // 判断线程池是否已完全终止
    public boolean isTerminated() { // 方法实现 }

    // 等待线程池终止,直到超时或被中断
    public boolean awaitTermination(long timeout, TimeUnit unit) throws InterruptedException { // 方法实现 }

    // 设置核心线程数,动态调整线程池
    public void setCorePoolSize(int corePoolSize) { // 方法实现 }

    // 设置最大线程数,限制线程池的最大容量
    public void setMaximumPoolSize(int maximumPoolSize) { // 方法实现 }

    // 设置空闲线程的存活时间
    public void setKeepAliveTime(long time, TimeUnit unit) { // 方法实现 }

    // 设置用于创建新线程的工厂
    public void setThreadFactory(ThreadFactory threadFactory) { // 方法实现 }

    // 设置任务拒绝策略
    public void setRejectedExecutionHandler(RejectedExecutionHandler handler) { // 方法实现 }

    // 返回当前线程池中的线程数量
    public int getPoolSize() { // 方法实现 }

    // 返回当前正在执行任务的线程数量
    public int getActiveCount() { // 方法实现 }

    // 返回线程池已完成的任务总数
    public long getCompletedTaskCount() { // 方法实现 }

    // 工作线程类,包装任务执行逻辑
    private final class Worker extends AbstractQueuedSynchronizer implements Runnable {
        final Thread thread;
        Runnable firstTask;
        volatile long completedTasks;

        // 初始化Worker并创建关联线程
        Worker(Runnable firstTask) { // 方法实现 }

        // 线程运行时的入口方法
        public void run() { // 方法实现 }

        // 判断锁是否被当前线程持有
        protected boolean isHeldExclusively() { // 方法实现 }

        // 尝试获取锁
        protected boolean tryAcquire(int unused) { // 方法实现 }

        // 尝试释放锁
        protected boolean tryRelease(int unused) { // 方法实现 }

        // 中断线程(如果已启动)
        void interruptIfStarted() { // 方法实现 }
    }

    // 默认拒绝策略:抛出异常
    public static class AbortPolicy implements RejectedExecutionHandler {
        public void rejectExecution(Runnable r, ThreadPoolExecutor e) { // 方法实现 }
    }

    // 调用者运行策略:由提交任务的线程执行任务
    public static class CallerRunsPolicy implements RejectedExecutionHandler {
        public void rejectExecution(Runnable r, ThreadPoolExecutor e) { // 方法实现 }
    }

    // 丢弃策略:直接丢弃新任务
    public static class DiscardPolicy implements RejectedExecutionHandler {
        public void rejectExecution(Runnable r, ThreadPoolExecutor e) { // 方法实现 }
    }

    // 丢弃最旧任务策略:丢弃队列中最老的任务
    public static class DiscardOldestPolicy implements RejectedExecutionHandler {
        public void rejectExecution(Runnable r, ThreadPoolExecutor e) { // 方法实现 }
    }

    // 任务执行前的回调(可由子类重写)
    protected void beforeExecute(Thread t, Runnable r) { // 方法实现 }

    // 任务执行后的回调(可由子类重写)
    protected void afterExecute(Runnable r, Throwable t) { // 方法实现 }

    // 线程池终止时的回调(可由子类重写)
    protected void terminated() { // 方法实现 }
}

5.接着,详细介绍一下:ThreadPoolExecutor类的关键方法:execute()、addWorker()、runWoker()、runWoker方法的getTask()

①核心入口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();
        if (! isRunning(recheck) && remove(command))
            reject(command);
        else if (workerCountOf(recheck) == 0)
            addWorker(null, false);
    }
    else if (!addWorker(command, false))
        reject(command);
}

可以总结出如下主要执行流程,当然看上述代码会有一些异常分支判断,可以自己顺理加到下述执行主流程里。

  1. 判断线程池的状态,如果不是RUNNING状态,直接执行拒绝策略
  2. 如果当前线程数 < 核心线程池,则新建一个线程来处理提交的任务
  3. 如果当前线程数 > 核心线程数且任务队列没满,则将任务放入任务队列等待执行
  4. 如果 核心线程池 < 当前线程池数 < 最大线程数,且任务队列已满,则创建新的线程执行提交的任务
  5. 如果当前线程数 > 最大线程数,且队列已满,则拒绝该任务

这个执行流程是 JUC 标准线程池提供的执行流程,主要用在 CPU 密集型场景下。像 Tomcat、Dubbo 这类框架,他们内部的线程池主要用来处理网络 IO 任务的,所以他们都对 JUC 线程池的执行流程进行了调整来支持 IO 密集型场景使用。他们提供了阻塞队列 TaskQueue,该队列继承 LinkedBlockingQueue,重写了 offer() 方法来实现执行流程的调整。具体可以看线程池需要会什么:一篇文章给你总结好了!!!-CSDN博客《线程池execute 方法的执行流程》

②addWorker()方法逻辑

private boolean addWorker(Runnable firstTask, boolean core) {
        retry:
        for (;;) {
            int c = ctl.get();
            // 获取当前池状态
            int rs = runStateOf(c);
         
            // 1.判断如果线程池状态 > SHUTDOWN,直接返回false,否则2
            // 2.如果线程池状态 = SHUTDOWN,并且firstTask不为null则直接返回false,因为SHUTDOWN状态的线程池不能在接受新任务,否则3
            // 3.如果线程池状态 = SHUTDOWN,并且firstTask == null,此时如果任务队列为空,则直接返回false
            if (rs >= SHUTDOWN &&
                ! (rs == SHUTDOWN &&
                   firstTask == null &&
                   ! workQueue.isEmpty()))
                return false;

            for (;;) {
                int wc = workerCountOf(c);
                // 1.如果当前线程池线程数大于等于CAPACITY(理论上的最大值5亿),则返回fasle
                // 2.如果创建核心线程情况下当前池线程数 >= corePoolSize,则返回false
                // 3.如果创建非核心线程情况下当前池线程数 >= maximumPoolSize,则返回false
                if (wc >= CAPACITY ||
                    wc >= (core ? corePoolSize : maximumPoolSize))
                    return false;
                // cas 增加当前池线程数量,成功则退出循环    
                if (compareAndIncrementWorkerCount(c))
                    break retry;
                c = ctl.get();  // Re-read ctl
                // cas 增加当前池线程数量失败(多线程并发),则重新获取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 {
            // 至此说明线程池状态校验通过,且增加池线程数量成功,则创建一个Worker线程来执行任务
            w = new Worker(firstTask);
            final Thread t = w.thread;
            if (t != null) {
                final ReentrantLock mainLock = this.mainLock;
                // 访问worker set时需要获取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());

                    // 1.当前池状态 < SHUTDOWN,也就是RUNNING状态,如果已经started,抛出异常
                    // 2.当前池状态 = SHUTDOWN,且firstTask == null,需要处理任务队列中的任务,如果已经started,抛出异常
                    if (rs < SHUTDOWN ||
                        (rs == SHUTDOWN && firstTask == null)) {
                        if (t.isAlive()) // precheck that t is startable
                            throw new IllegalThreadStateException();
                        // 刚创建线程添加到workers集合中
                        workers.add(w);
                        int s = workers.size();
                        // 判断更新历史最大线程数量
                        if (s > largestPoolSize)
                            largestPoolSize = s;
                        workerAdded = true;
                    }
                } finally {
                    mainLock.unlock();
                }
                if (workerAdded) {
                    // 启动新建线程
                    t.start();
                    workerStarted = true;
                }
            }
        } finally {
            if (! workerStarted)
                // 启动失败,workerCount--,workers里移除该worker
                addWorkerFailed(w);
        }
        return workerStarted;
    }

③runWorker()方法逻辑

线程池中的线程并不是直接用的Thread类,而是定义了一个内部工作线程Worker类,实现了AQS以及Runnable接口,然后持有一个Thread类的引用及一个firstTask(创建后第一个要执行的任务),每个Worker线程启动后会执行run()方法,该方法会调用执行外层runWorker(Worker w)方法

final void runWorker(Worker w) {
    Thread wt = Thread.currentThread();
    Runnable task = w.firstTask;
    w.firstTask = null;
    w.unlock(); // allow interrupts
    boolean completedAbruptly = true;
    try {
        // 1.如果task不为空,则作为该线程的第一个任务直接执行
        // 2.如果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
            // 线程池状态 >= STOP,则中断线程
            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 {
                // 任务置为null,重新获取新任务,完成数++
                task = null;
                w.completedTasks++;
                w.unlock();
            }
        }
        completedAbruptly = false;
    } finally {
        // 无任务可执行,执行worker销毁逻辑
        processWorkerExit(w, completedAbruptly);
    }
}

④getTask()方法逻辑:被runWoker()调用

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

    for (;;) {
        int c = ctl.get();
        int rs = runStateOf(c);
        
        // 以下两种情况递减工作线程数量
        // 1. rs >= STOP
        // 2. rs == SHUTDOWN && workQueue.isEmpty()
        if (rs >= SHUTDOWN && (rs >= STOP || workQueue.isEmpty())) {
            decrementWorkerCount();
            return null;
        }

        int wc = workerCountOf(c);

        // Are workers subject to culling?
        // 允许核心线程超时 或者 当前线程数 > 核心线程数,有可能发生超时关闭
        boolean timed = allowCoreThreadTimeOut || wc > corePoolSize;

        // wc什么情况 > maximumPoolSize,调用setMaximumPoolSize()方法将maximumPoolSize调小了,会发生这种情况,此时需要关闭多余线程
        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;
        }
    }
}

最后梳理一下:

主要围绕 Java 线程池相关类展开介绍,依次提及了 Executor 接口、ExecutorService 接口、AbstractExecutorService 抽象类、ThreadPoolExecutor 类 。并且聚焦于 ThreadPoolExecutor 类,列举了其关键方法,如 execute()addWorker() 等,还针对部分方法打算介绍执行逻辑,像 execute() 方法执行逻辑、addWorker() 方法逻辑、runWorker() 方法逻辑,以及说明 getTask() 方法被 runWorker() 调用并准备阐述其逻辑。

以上内容比较详细的介绍了ThreadPoolExecutor的继承体系,以及相关的核心源码,谢谢您的观看。

你可能感兴趣的:(Java,线程池,线程池源码分析,Java,并发编程,Executor,多线程,源码解读,ThreadPoolExt)