欢迎光临
我们一直在努力

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

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 () 方法核心流程
  • 工作线程数 < corePoolSize → 创建核心线程执行任务
  • 线程池 RUNNING 且队列未满 → 任务入队
  • 队列满且工作线程数 < maximumPoolSize → 创建非核心线程执行任务
  • 队列和最大线程数均满 → 执行拒绝策略
  • (2)线程回收机制
    • 非核心线程:空闲时间超过 keepAliveTime 时,通过 poll(keepAliveTime) 超时回收
    • 核心线程:默认不回收,allowCoreThreadTimeOut=true 时可回收
    • 回收触发:getTask() 方法返回 null → 线程退出循环 → 执行 processWorkerExit() 善后
    (3)异常处理机制
    • 任务执行抛异常 → 线程退出 → processWorkerExit() 会创建新线程补充核心线程数
    • 核心线程数不会因异常全部消失
    赞(0)
    未经允许不得转载:171主机测评 » Java 线程池 — ThreadPoolExecutor
    分享到: 更多 (0)

    评论 抢沙发

    • 昵称 (必填)
    • 邮箱 (必填)
    • 网址