Skip to content

ThreadPollExecutor 是什么?

约 771 字大约 3 分钟

多线程与并发京东

2025-03-25

⭐ 题目日期:

京东 - 2024/12/26

📝 题解:

ThreadPoolExecutor 是 Java 中用于管理线程池的核心类(位于 java.util.concurrent 包),它提供了一种高效、灵活的机制来执行异步任务。通过复用线程、控制并发数量及管理任务队列,它能显著提升多线程程序的性能和稳定性。


核心作用

  1. 线程复用:避免频繁创建和销毁线程的开销。
  2. 资源管理:限制并发线程数,防止系统过载。
  3. 任务调度:按策略处理任务提交、排队、执行和拒绝。

关键参数

创建 ThreadPoolExecutor 需配置以下参数:

  1. 核心线程数(corePoolSize)

    • 线程池长期保留的线程数量,即使空闲也不会销毁(除非设置 allowCoreThreadTimeOut)。
  2. 最大线程数(maximumPoolSize)

    • 线程池允许创建的最大线程数。当任务队列满时,会创建新线程直到达到此值。
  3. 任务队列(workQueue)

    • 用于缓存未执行的任务。常见类型:
      • LinkedBlockingQueue(无界队列,可能导致内存溢出)
      • ArrayBlockingQueue(有界队列)
      • SynchronousQueue(直接传递任务,不缓存)
  4. 线程存活时间(keepAliveTime)

    • 非核心线程空闲时的存活时间,超时后自动销毁。
  5. 拒绝策略(RejectedExecutionHandler)

    • 当线程池和队列已满时,处理新任务的策略。常见策略:
      • AbortPolicy(默认):抛出 RejectedExecutionException
      • CallerRunsPolicy:由提交任务的线程直接执行。
      • DiscardPolicy:静默丢弃任务。
      • DiscardOldestPolicy:丢弃队列中最旧的任务,重新提交新任务。

工作流程

  1. 提交任务时,若当前线程数 < 核心线程数,直接创建新线程执行。
  2. 若线程数 ≥ 核心数,任务进入队列等待。
  3. 若队列已满且线程数 < 最大线程数,创建新线程执行任务。
  4. 若队列和线程数均满,触发拒绝策略。

使用示例

import java.util.concurrent.*;

public class Example {
    public static void main(String[] args) {
        // 创建线程池
        ThreadPoolExecutor executor = new ThreadPoolExecutor(
            2,      // 核心线程数
            4,      // 最大线程数
            60,     // 空闲线程存活时间(秒)
            TimeUnit.SECONDS,
            new ArrayBlockingQueue<>(10),  // 容量为10的任务队列
            new ThreadPoolExecutor.CallerRunsPolicy()  // 拒绝策略
        );

        // 提交任务
        for (int i = 0; i < 15; i++) {
            executor.execute(() -> {
                System.out.println("任务执行线程: " + Thread.currentThread().getName());
            });
        }

        // 关闭线程池
        executor.shutdown();
    }
}

常见线程池工具

Java 的 Executors 工具类提供了一些预配置的线程池(底层基于 ThreadPoolExecutor):

  • newFixedThreadPool:固定线程数,使用无界队列。
  • newCachedThreadPool:线程数可无限扩展,适合短时任务。
  • newSingleThreadExecutor:单线程串行执行任务。
  • newScheduledThreadPool:支持定时或周期性任务。

注意事项

  • 避免无界队列:可能导致内存溢出(如 LinkedBlockingQueue 未指定容量)。
  • 合理设置线程数:根据任务类型(CPU密集型、IO密集型)调整。
  • 正确关闭线程池:使用 shutdown() 平滑关闭,或 shutdownNow() 强制中断。

通过合理配置 ThreadPoolExecutor,可以有效平衡系统资源与任务吞吐量,是多线程编程中的关键组件。