Java 线程池参数详解与生产环境最佳实践(避坑指南)

一、为什么不推荐 Executors

阿里开发手册明确禁止使用 Executors 创建线程池,原因是:
  • newFixedThreadPool 使用无界队列 LinkedBlockingQueue,可能 OOM
  • newCachedThreadPool 最大线程数为 Integer.MAX_VALUE,可能创建海量线程
正确做法是直接 new ThreadPoolExecutor(...)。

二、七个核心参数

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

三、任务提交后的执行流程

CODE
提交任务
  ├─ 当前线程数 < corePoolSize → 创建核心线程执行
  ├─ 核心线程已满 → 任务入队
  │    └─ 队列已满 且 线程数 < maximumPoolSize → 创建非核心线程
  │         └─ 线程数已达 maximumPoolSize → 执行拒绝策略

关键认知:队列满了才会创建非核心线程,而不是核心线程满了就创建。

四、队列怎么选

| 队列 | 特点 | 风险 | | --- | --- | --- | | ArrayBlockingQueue | 有界数组队列 | 需合理设置容量 | | LinkedBlockingQueue | 默认无界 | 可能 OOM | | SynchronousQueue | 不存储元素 | 需配合大 maxPoolSize | | PriorityBlockingQueue | 优先级 | 无界 |

五、线程数怎么算

Java
// CPU 密集型:线程数 ≈ CPU 核数 + 1
int cpuCount = Runtime.getRuntime().availableProcessors();

// IO 密集型:线程数 ≈ CPU 核数 * (1 + 等待时间/计算时间)
// 经验值:CPU 核数 * 2

六、生产配置示例

Java
@Bean("orderExecutor")
public ThreadPoolExecutor orderExecutor() {
    ThreadFactory factory = new ThreadFactoryBuilder()
            .setNameFormat("order-pool-%d")
            .setUncaughtExceptionHandler((t, e) -> log.error("线程异常", e))
            .build();

    return new ThreadPoolExecutor(
            8, 16, 60L, TimeUnit.SECONDS,
            new ArrayBlockingQueue<>(2000),
            factory,
            new ThreadPoolExecutor.CallerRunsPolicy()
    );
}

拒绝策略选择:

  • AbortPolicy:抛异常(默认),适合关键任务
  • CallerRunsPolicy:让提交者自己执行,天然限流(推荐)
  • DiscardPolicy:静默丢弃,慎用
  • DiscardOldestPolicy:丢弃队头,慎用

七、记得给线程命名

Java
// 反例:pool-1-thread-1,出问题时无法定位
// 正例:order-pool-3,一眼看出是哪个业务池

发表于天涯网络_专业开发者社区 - 个人技术分享

打赏作者 已有 0 人打赏,共 ¥0.00
我的打赏
天眼管理员
天眼管理员
Lv10 专业会员 原创 3 粉丝 1463

天眼技术社区官方管理员账号

  • 3文章
  • 25总阅读
  • 0获赞
  • 1463粉丝

评论(0)

💬

还没有评论,来说两句吧