NiceOffer

八股文解析

线程池参数与拒绝策略实战

Java线程池并发八股文

线程池参数与拒绝策略实战

一句话结论

  • 线程池不是越大越好:CPU 密集型 ≈ 核数 +1,IO 密集型 ≈ 核数 × (1 + 平均等待/平均计算)
  • 拒绝策略要匹配业务:核心请求用 CallerRunsPolicy,可丢弃用 DiscardPolicy

面试标准答法

ThreadPoolExecutor 七大参数

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

执行流程:

  1. 核心线程未满 → 直接创建核心线程执行
  2. 核心线程已满 → 入队
  3. 队列已满 → 创建非核心线程
  4. 最大线程已满 → 触发拒绝策略

四种拒绝策略

策略行为适用场景
AbortPolicyRejectedExecutionException默认,核心任务不可丢
CallerRunsPolicy由调用线程直接执行减缓提交速度,保证执行
DiscardPolicy静默丢弃允许丢失的监控/日志
DiscardOldestPolicy丢弃队列最老任务队列积压严重时

队列选择

  • SynchronousQueue:不存储,直接交接(CachedThreadPool
  • LinkedBlockingQueue:无界,可能 OOM(FixedThreadPool
  • ArrayBlockingQueue:有界,推荐生产使用
  • PriorityBlockingQueue:优先级调度

线程数估算

  • CPU 密集型N_cpu + 1(如加密、压缩、算法)
  • IO 密集型N_cpu × (1 + W/C),W=等待时间,C=计算时间(如 RPC、DB、文件)

经验值:Web 服务常配 N_cpu × 2N_cpu × 4,再结合压测调整。

常见追问

追问要点
为什么阿里规范不推荐 ExecutorsFixedThreadPoolSingleThreadPool 用无界队列,可能 OOM;CachedThreadPool 可创建 Integer.MAX_VALUE 线程
keepAliveTime 对核心线程生效吗?默认不生效,设置 allowCoreThreadTimeOut(true) 后生效
如何监控线程池?自定义 ThreadPoolExecutor 重写 beforeExecute / afterExecute,或接入 Micrometer/Prometheus

面试回答模板(30 秒版)

延伸准备

  • 能手写自定义线程池 + 拒绝策略(进 MQ)
  • 能解释 ThreadLocal 在线程池中的内存泄漏风险
  • 能对比 ForkJoinPoolThreadPoolExecutor 适用场景