ThreadPoolExecutor 核心源码逻辑讲解
                           
天天向上
发布: 2025-04-26 18:38:06

原创
146 人浏览过

我这就给你打包一版超清晰又能背的《ThreadPoolExecutor 核心源码逻辑讲解》,简单直接,面试一讲就很能打!


1. execute() 方法内部执行顺序

当你调用 executor.execute(Runnable task) 提交一个任务时,内部流程就是下面这套逻辑:


标准三步走:

  1. 如果运行的线程数 < corePoolSize,立刻创建新线程执行任务。
  2. 如果线程数 ≥ corePoolSize,任务加入到任务队列(workQueue)等待执行。
  3. 如果队列也满了,且线程数 < maximumPoolSize,则创建新线程执行任务。
  4. 如果线程数已到 maximumPoolSize 且队列也满了,执行拒绝策略(RejectedExecutionHandler)。

对应源码(摘抄核心版,理解即可,不用死记)

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

2. 为什么是这个顺序?(面试官常问)

答:

这样设计可以最大程度地提高线程利用率,避免频繁地创建和销毁线程,同时还能有效控制内存占用和CPU资源,确保系统稳定性。

更具体地说:

  • 优先使用核心线程处理任务 ➔ 快速响应请求
  • 任务堆积时利用队列缓冲 ➔ 控制线程数量,避免爆炸增长
  • 极端情况下再扩展最大线程数 ➔ 兜底处理高峰请求
  • 都扛不住时拒绝新任务 ➔ 保系统稳定,防止雪崩

3. 超快速记忆版口诀

直接送你一个口诀,记下来,回答超快:

先加核心 ➔ 进队列 ➔ 再扩容 ➔ 最后拒绝


4. 小细节(如果面试官很细问的话)

  • addWorker(task, true)true 表示用核心线程
  • addWorker(task, false)false 表示用最大线程池里的空位
  • ctl 是个控制器,记录线程池状态 + 线程数量
  • isRunning() 判断线程池是否还在正常运行

(遇到追问,稍微提一点就够了,不需要深入到位运算、AQS 这种底层细节,除非是资深岗位)


总结一版万能说法(面试收尾)

ThreadPoolExecutor 的 execute 方法采用了先用核心线程、再放队列、再扩展最大线程、最后拒绝的策略,兼顾了性能、资源利用率和系统稳定性,是工业界最经典的线程池设计之一。


更多详细内容请关注其他相关文章!

发表回复 0

Your email address will not be published. Required fields are marked *