​Executors​​ 类提供了多种创建线程池的静态方法,主要分为以下几类:

1. 固定大小线程池

// 创建固定大小的线程池
ExecutorService fixedThreadPool = Executors.newFixedThreadPool(int nThreads);

特点:

  • 核心线程数 = 最大线程数 = nThreads
  • 使用无界队列(LinkedBlockingQueue)
  • 线程空闲时不会被回收
  • 适合负载较重的服务器

2. 单线程线程池

// 创建单线程的线程池
ExecutorService singleThreadExecutor = Executors.newSingleThreadExecutor();

特点:

  • 只有一个工作线程
  • 保证任务按顺序执行
  • 使用无界队列
  • 适合需要顺序执行任务的场景

3. 缓存线程池

// 创建可缓存的线程池
ExecutorService cachedThreadPool = Executors.newCachedThreadPool();

特点:

  • 核心线程数 = 0,最大线程数 = Integer.MAX_VALUE
  • 使用同步队列(SynchronousQueue)
  • 空闲线程60秒后回收
  • 适合大量短时异步任务

4. 定时/周期线程池

// 创建定时任务线程池
ScheduledExecutorService scheduledThreadPool = Executors.newScheduledThreadPool(int corePoolSize);

特点:

  • 可以执行定时任务和周期性任务
  • 使用延迟队列(DelayedWorkQueue)
  • 适合定时任务场景

5. 工作窃取线程池(Java 8+)

// 创建工作窃取线程池(ForkJoinPool)
ExecutorService workStealingPool = Executors.newWorkStealingPool();
// 或指定并行级别
ExecutorService workStealingPool = Executors.newWorkStealingPool(int parallelism);

特点:

  • 基于 ForkJoinPool 实现
  • 使用工作窃取算法,提高CPU利用率
  • 适合计算密集型任务

详细对比表格

方法

核心线程数

最大线程数

队列类型

线程存活时间

适用场景

newFixedThreadPool

nThreads

nThreads

LinkedBlockingQueue

无限

负载较重的服务器,控制并发数

newSingleThreadExecutor

1

1

LinkedBlockingQueue

无限

顺序执行任务,保证顺序性

newCachedThreadPool

0

Integer.MAX_VALUE

SynchronousQueue

60秒

大量短时异步任务,弹性伸缩

newScheduledThreadPool

corePoolSize

Integer.MAX_VALUE

DelayedWorkQueue

无限

定时任务,周期性任务

newWorkStealingPool

CPU核心数

无限制

内部队列

无限

计算密集型任务,并行处理

代码示例

import java.util.concurrent.*;

public class ExecutorsDemo {
    public static void main(String[] args) {
        // 1. 固定大小线程池
        ExecutorService fixedPool = Executors.newFixedThreadPool(5);
        
        // 2. 单线程线程池
        ExecutorService singleThreadPool = Executors.newSingleThreadExecutor();
        
        // 3. 缓存线程池
        ExecutorService cachedPool = Executors.newCachedThreadPool();
        
        // 4. 定时线程池
        ScheduledExecutorService scheduledPool = Executors.newScheduledThreadPool(3);
        
        // 5. 工作窃取线程池
        ExecutorService workStealingPool = Executors.newWorkStealingPool();
        
        // 使用示例
        fixedPool.execute(() -> System.out.println("FixedThreadPool任务"));
        
        scheduledPool.schedule(() -> {
            System.out.println("3秒后执行");
        }, 3, TimeUnit.SECONDS);
        
        // 关闭线程池
        fixedPool.shutdown();
        singleThreadPool.shutdown();
        cachedPool.shutdown();
        scheduledPool.shutdown();
        workStealingPool.shutdown();
    }
}

潜在问题与注意事项

1. 内存溢出风险

// 以下两种方式使用无界队列,可能导致OOM
ExecutorService fixedPool = Executors.newFixedThreadPool(10);
ExecutorService singlePool = Executors.newSingleThreadExecutor();

// 缓存线程池可能创建过多线程导致OOM
ExecutorService cachedPool = Executors.newCachedThreadPool();

2. 推荐手动创建线程池

// 更推荐的方式:手动创建ThreadPoolExecutor
ThreadPoolExecutor executor = new ThreadPoolExecutor(
    5, // 核心线程数
    10, // 最大线程数
    60L, // 空闲线程存活时间
    TimeUnit.SECONDS, // 时间单位
    new ArrayBlockingQueue<>(100), // 有界队列
    Executors.defaultThreadFactory(), // 线程工厂
    new ThreadPoolExecutor.CallerRunsPolicy() // 拒绝策略
);

3. 阿里巴巴开发规范建议

根据《阿里巴巴Java开发手册》:

  • 线程池不允许使用 ​​Executors​​ 创建
  • 推荐使用 ​​ThreadPoolExecutor​​ 构造函数创建
  • 原因:规避资源耗尽风险

4. 选择合适的拒绝策略

ThreadPoolExecutor executor = new ThreadPoolExecutor(
    5, 10, 60, TimeUnit.SECONDS,
    new ArrayBlockingQueue<>(100),
    new ThreadPoolExecutor.AbortPolicy() // 默认:抛出异常
    // new ThreadPoolExecutor.CallerRunsPolicy() // 调用者运行
    // new ThreadPoolExecutor.DiscardOldestPolicy() // 丢弃最老任务
    // new ThreadPoolExecutor.DiscardPolicy() // 直接丢弃
);

总结

虽然 ​​Executors​​​ 提供了便捷的线程池创建方法,但在生产环境中,建议手动创建 ​​ThreadPoolExecutor​​ ,以便更好地控制线程池参数,避免潜在的内存和性能问题。

简单记忆:

  • ​Fixed​​:固定大小,无界队列
  • ​Single​​:单线程,顺序执行
  • ​Cached​​:弹性伸缩,短时任务
  • ​Scheduled​​:定时任务
  • ​WorkStealing​​:工作窃取,并行计算

资料下载、系统化学习Java并发编程,请查阅作者的视频课:

 ​​《Java多线程与并发编程原理详解》​ 

Logo

openEuler 是由开放原子开源基金会孵化的全场景开源操作系统项目,面向数字基础设施四大核心场景(服务器、云计算、边缘计算、嵌入式),全面支持 ARM、x86、RISC-V、loongArch、PowerPC、SW-64 等多样性计算架构

更多推荐