Skip to content

线程池

线程池是 Java 并发编程中最重要的工具之一,它能够有效管理线程资源,提高应用程序的性能和稳定性。

1. 为什么使用线程池

优势说明
降低资源消耗重用已创建的线程,避免频繁创建销毁
提高响应速度任务到达时无需等待线程创建
便于管理统一分配、调优和监控
控制并发数防止无限制创建线程导致系统崩溃

2. 创建线程池

2.1 Executors 工厂方法(不推荐)

java
import java.util.concurrent.*;

// 固定大小线程池
ExecutorService fixedPool = Executors.newFixedThreadPool(10);

// 缓存线程池(线程数不固定)
ExecutorService cachedPool = Executors.newCachedThreadPool();

// 单线程池
ExecutorService singlePool = Executors.newSingleThreadExecutor();

// 定时任务线程池
ScheduledExecutorService scheduledPool = Executors.newScheduledThreadPool(5);

⚠️ 阿里规范:不推荐使用 Executors 创建线程池,因为可能导致 OOM。

2.2 ThreadPoolExecutor(推荐)

java
ThreadPoolExecutor executor = new ThreadPoolExecutor(
    5,                      // corePoolSize: 核心线程数
    10,                     // maximumPoolSize: 最大线程数
    60L,                    // keepAliveTime: 空闲线程存活时间
    TimeUnit.SECONDS,       // 时间单位
    new LinkedBlockingQueue<>(100),  // 工作队列
    Executors.defaultThreadFactory(), // 线程工厂
    new ThreadPoolExecutor.AbortPolicy() // 拒绝策略
);

3. 七大核心参数

java
public ThreadPoolExecutor(
    int corePoolSize,                        // 核心线程数
    int maximumPoolSize,                     // 最大线程数
    long keepAliveTime,                      // 空闲线程存活时间
    TimeUnit unit,                           // 时间单位
    BlockingQueue<Runnable> workQueue,       // 工作队列
    ThreadFactory threadFactory,             // 线程工厂
    RejectedExecutionHandler handler         // 拒绝策略
)

3.1 corePoolSize(核心线程数)

属性说明
作用线程池中始终保持存活的线程数量
默认行为核心线程创建后不会被回收

配置建议

  • CPU 密集型corePoolSize = CPU核心数 + 1
  • IO 密集型corePoolSize = CPU核心数 × 2
java
int cpuCores = Runtime.getRuntime().availableProcessors();

3.2 maximumPoolSize(最大线程数)

属性说明
作用线程池允许创建的最大线程数量
约束必须 >= corePoolSize

3.3 keepAliveTime(空闲存活时间)

属性说明
作用非核心线程空闲时的存活时间
生效范围默认只对非核心线程生效

3.4 workQueue(工作队列)

队列类型特点适用场景
ArrayBlockingQueue有界队列推荐,需限制队列大小
LinkedBlockingQueue默认无界需设置容量,防止 OOM
SynchronousQueue不存储元素快速响应场景
PriorityBlockingQueue优先级队列任务有优先级区分

3.5 threadFactory(线程工厂)

java
ThreadFactory customFactory = new ThreadFactory() {
    private final AtomicInteger counter = new AtomicInteger(1);
    
    @Override
    public Thread newThread(Runnable r) {
        Thread thread = new Thread(r);
        thread.setName("order-pool-" + counter.getAndIncrement());
        thread.setDaemon(false);
        return thread;
    }
};

3.6 handler(拒绝策略)

策略行为
AbortPolicy抛出异常(默认)
CallerRunsPolicy调用者线程执行
DiscardPolicy静默丢弃
DiscardOldestPolicy丢弃最老任务

4. 工作流程

                    提交任务


              ┌────────────────┐
              │ 线程数 < 核心数?│
              └────────────────┘
                 │         │
                YES        NO
                 │         │
                 ▼         ▼
            创建核心线程  ┌────────────┐
            执行任务     │ 队列未满?  │
                        └────────────┘
                           │       │
                          YES      NO
                           │       │
                           ▼       ▼
                       任务入队  ┌──────────────┐
                       等待执行 │ 线程数 < 最大?│
                               └──────────────┘
                                  │        │
                                 YES       NO
                                  │        │
                                  ▼        ▼
                             创建非核心   执行拒绝
                             线程执行     策略

5. 核心线程生命周期管理

5.1 allowCoreThreadTimeOut

java
ThreadPoolExecutor executor = new ThreadPoolExecutor(
    5, 10, 60L, TimeUnit.SECONDS,
    new LinkedBlockingQueue<>(100)
);

// 开启核心线程超时回收
executor.allowCoreThreadTimeOut(true);

// 此时所有线程空闲60秒后都会被回收
// 线程池可能缩减到 0 个线程
场景是否开启
任务频繁❌ 关闭
任务间隔长✅ 开启

5.2 prestartAllCoreThreads

java
// 预启动所有核心线程
int started = executor.prestartAllCoreThreads();

// 预启动一个核心线程
boolean success = executor.prestartCoreThread();

使用场景:Web 应用启动时预热,避免首批请求冷启动延迟。

6. 提交任务

java
ExecutorService executor = Executors.newFixedThreadPool(5);

// execute:无返回值
executor.execute(() -> {
    System.out.println("执行任务");
});

// submit:有返回值
Future<String> future = executor.submit(() -> {
    Thread.sleep(1000);
    return "任务结果";
});

String result = future.get(); // 阻塞获取结果

7. 关闭线程池

java
// 优雅关闭:不再接受新任务,等待已提交任务完成
executor.shutdown();

// 立即关闭:尝试中断正在执行的任务
List<Runnable> notExecuted = executor.shutdownNow();

// 等待关闭完成
if (!executor.awaitTermination(60, TimeUnit.SECONDS)) {
    executor.shutdownNow();
}

8. 最佳实践

8.1 生产环境配置示例

java
@Configuration
public class ThreadPoolConfig {
    
    @Bean
    public ThreadPoolExecutor orderProcessPool() {
        int cpuCores = Runtime.getRuntime().availableProcessors();
        
        ThreadPoolExecutor executor = new ThreadPoolExecutor(
            cpuCores * 2,           // 核心线程数
            cpuCores * 4,           // 最大线程数
            60L, TimeUnit.SECONDS,  // 空闲存活时间
            new ArrayBlockingQueue<>(500),  // 有界队列
            new ThreadFactoryBuilder()
                .setNameFormat("order-pool-%d")
                .build(),
            new ThreadPoolExecutor.CallerRunsPolicy()  // 拒绝策略
        );
        
        // 预热线程池
        executor.prestartAllCoreThreads();
        
        return executor;
    }
}

8.2 监控线程池

java
ThreadPoolExecutor executor = ...;

// 监控指标
System.out.println("核心线程数: " + executor.getCorePoolSize());
System.out.println("当前线程数: " + executor.getPoolSize());
System.out.println("活跃线程数: " + executor.getActiveCount());
System.out.println("历史最大线程数: " + executor.getLargestPoolSize());
System.out.println("已完成任务数: " + executor.getCompletedTaskCount());
System.out.println("队列大小: " + executor.getQueue().size());