Java 线程池 — ThreadPoolExecutor

一、线程池基础概念

1. 核心定义

线程池:基于池化思想管理线程的工具,维护多个线程等待分配任务,避免线程创建 / 销毁的开销,控制线程数量防止资源耗尽。

2. 核心优势

  • 降低资源消耗:复用线程,减少创建 / 销毁损耗
  • 提高响应速度:任务到达无需等待线程创建
  • 提升可管理性:统一分配、调优和监控线程资源
  • 扩展功能丰富:支持定时 / 周期性任务(如 ScheduledThreadPoolExecutor)

二、线程池创建方式

1. 推荐方式:ThreadPoolExecutor 构造器

核心构造方法
复制代码
public ThreadPoolExecutor(
    int corePoolSize,        // 核心线程数
    int maximumPoolSize,     // 最大线程数
    long keepAliveTime,      // 非核心线程空闲存活时间
    TimeUnit unit,           // 存活时间单位
    BlockingQueue<Runnable> workQueue,  // 任务队列
    ThreadFactory threadFactory,        // 线程工厂
    RejectedExecutionHandler handler    // 拒绝策略
)
核心参数详解
参数 作用 关键说明
corePoolSize 核心线程数 初始化时无线程,任务到来时创建,默认不会回收(allowCoreThreadTimeOut 可修改)
maximumPoolSize 最大线程数 核心线程 + 非核心线程的上限,队列满时才会创建非核心线程
keepAliveTime 非核心线程空闲时间 corePoolSize == maximumPoolSize 时无效
workQueue 任务缓冲队列 核心线程满时存放任务,分有界 / 无界 / 同步队列
threadFactory 线程创建工厂 默认 Executors.defaultThreadFactory (),可自定义线程名称、优先级等
handler 拒绝策略 队列和最大线程数均满时触发

2. 不推荐方式:Executors 静态方法

弊端(阿里巴巴 Java 开发手册强制要求避免)
  • FixedThreadPool/SingleThreadExecutor:队列长度为 Integer.MAX_VALUE,易堆积任务导致 OOM
  • CachedThreadPool/ScheduledThreadPool:最大线程数为 Integer.MAX_VALUE,易创建大量线程导致 OOM
Executors 线程池类型对比
类型 线程构成 核心特点 应用场景
FixedThreadPool 核心线程固定 核心线程不回收,队列无界 控制最大并发数
ScheduledThreadPool 核心 + 非核心线程 非核心线程闲置立即回收 定时 / 周期性任务
CachedThreadPool 仅非核心线程 60s 空闲回收,线程数无界 短耗时、数量多的任务
SingleThreadExecutor 1 个核心线程 任务顺序执行,无需同步 单线程串行任务(如数据库操作)

三、核心组件详解

1. 任务队列(workQueue)类型

  • ArrayBlockingQueue(有界队列):长度固定,队列满时创建非核心线程,最大线程满则触发拒绝策略
  • LinkedBlockingQueue(无界队列):长度无限,易因任务堆积导致 OOM
  • SynchronousQueue(同步队列):长度为 0,不缓存任务,直接移交线程执行

2. 拒绝策略(RejectedExecutionHandler)

策略类型 核心逻辑 适用场景
AbortPolicy(默认) 丢弃任务并抛出 RejectedExecutionException 关键业务(需及时感知异常)
DiscardPolicy 丢弃任务不抛异常 无关紧要的业务
DiscardOldestPolicy 丢弃队列最久任务,重试提交当前任务 允许丢弃老任务的场景
CallerRunsPolicy 由提交任务的主线程执行 需所有任务执行完毕的场景

四、线程池使用方法

1. 任务提交方式

方法 返回值 适用场景
execute(Runnable command) 无需返回结果的任务
submit(Runnable task) Future<?> 需判断任务是否完成
submit(Callable<T> task) Future<T> 需获取任务执行结果

2. 批量任务执行

  • invokeAll(Collection<? extends Callable<T>> tasks):等待所有任务完成,返回所有结果
  • invokeAll(Collection<? extends Callable<T>> tasks, long timeout, TimeUnit unit):超时取消未完成任务
  • invokeAny(Collection<? extends Callable<T>> tasks):返回第一个完成的任务结果
  • invokeAny(Collection<? extends Callable<T>> tasks, long timeout, TimeUnit unit):超时取消未完成任务

3. 定时 / 周期性任务(ScheduledThreadPoolExecutor)

  • schedule(Runnable/Callable task, long delay, TimeUnit unit):延时一次执行
  • scheduleAtFixedRate(Runnable task, long initialDelay, long period, TimeUnit unit):固定周期执行(以上次任务开始时间计算)
  • scheduleWithFixedDelay(Runnable task, long initialDelay, long delay, TimeUnit unit):固定间隔执行(以上次任务结束时间计算)

4. 线程池关闭

方法 核心逻辑 线程池状态
shutdown() 不接收新任务,执行完队列中任务 SHUTDOWN
shutdownNow() 不接收新任务,中断正在执行的任务,返回未执行任务 STOP
isTerminated() 所有任务执行完毕返回 true TERMINATED

关闭方法对比

五、线程池参数设计公式

1. 核心线程数(corePoolSize)

  • 公式:核心线程数 = (每秒任务数 × 单个任务执行时间)× 80%(二八原则)
  • 示例:每秒 100 个任务,单个任务 0.1 秒 → 100×0.1×0.8=8(实际取 10 优化)

2. 任务队列长度(workQueue)

  • 公式:队列长度 = 核心线程数 / 单个任务执行时间 × 2
  • 示例:核心线程数 10,单个任务 0.1 秒 → 10/0.1×2=200

3. 最大线程数(maximumPoolSize)

  • 公式:最大线程数 = (最大每秒任务数 - 队列长度)× 单个任务执行时间
  • 示例:最大每秒 1000 个任务,队列长度 200,单个任务 0.1 秒 →(1000-200)×0.1=80

4. 空闲时间(keepAliveTime)

  • 无固定公式,根据系统压力和任务间隔调整(默认 60s 可参考)

六、线程池核心原理

1. 任务执行流程

2. 线程池状态流转

线程池通过 ctl(AtomicInteger)维护状态(高 3 位)和工作线程数(低 29 位),五种状态流转如下:

3. 关键源码逻辑

(1)execute () 方法核心流程
  1. 工作线程数 < corePoolSize → 创建核心线程执行任务
  2. 线程池 RUNNING 且队列未满 → 任务入队
  3. 队列满且工作线程数 < maximumPoolSize → 创建非核心线程执行任务
  4. 队列和最大线程数均满 → 执行拒绝策略
(2)线程回收机制
  • 非核心线程:空闲时间超过 keepAliveTime 时,通过 poll(keepAliveTime) 超时回收
  • 核心线程:默认不回收,allowCoreThreadTimeOut=true 时可回收
  • 回收触发:getTask() 方法返回 null → 线程退出循环 → 执行 processWorkerExit() 善后
(3)异常处理机制
  • 任务执行抛异常 → 线程退出 → processWorkerExit() 会创建新线程补充核心线程数
  • 核心线程数不会因异常全部消失
相关推荐
咖啡八杯1 小时前
GoF设计模式——解释器模式
java·后端·spring·设计模式
优橙教育2 小时前
5G网优培训 vs Java开发:转行选哪个?
java·开发语言·5g
糖果店的幽灵2 小时前
【DeepAgents 从入门到精通】Context Management 上下文管理
java·人工智能·后端·spring·中间件·langgraph·deepagents
想会飞的蒲公英3 小时前
计算机怎样读取中文文本:编码、清洗与标准化
人工智能·python·自然语言处理
腻害兔3 小时前
【若依项目-产品经理视角】RuoYi-Vue-Pro 源码拆解:字典、短信、邮件、通知——后台系统的“基础设施四件套“!
java·前端·vue.js·产品经理·ai编程
SeaTunnel3 小时前
从 Python Script 地狱到标准化数据集成框架
大数据·开发语言·python·程序员·代码·seatunnel
深度研习笔记4 小时前
OpenCV工业视觉实战09|项目EXE打包+工控机无环境部署+后台常驻运行,彻底脱离Python环境,完成项目最终交付
python·opencv·webpack
碎光拾影4 小时前
ARM交叉工具链各工具作用及IMX6ULL平台LED+蜂鸣器裸机程序实现
java·开发语言·数据库
CCPC不拿奖不改名4 小时前
大模型推理架构与开源生态知识整理
数据库·windows·python·架构·langchain·开源·github
Marst Code4 小时前
(python)2026Plotly 库评估:交互式可视化到底值不值得引入?
开发语言·python