线程池调优

一:

ThreadPoolExecutor 核心七大参数:
public ThreadPoolExecutor(int corePoolSize,
            int maximumPoolSize,
            long keepAliveTime,
            TimeUnit unit,
            BlockingQueue<Runnable> workQueue,
            ThreadFactory threadFactory,
            RejectedExecutionHandler handler)
1. corePoolSize (核心线程数)
2. maximumPoolSize (最大线程数)
3. keepAliveTime + unit (线程存活时间)
4. workQueue (工作队列)
5. threadFactory (线程工厂)
6. handler (拒绝策略/饱和策略)
定义:当线程池已经关闭或线程池和队列都已达到饱和状态(即线程数达到 maximumPoolSize 且 workQueue 已满)时,对新提交的任务采取的处理策略。

二:

线程池的工作流程(非常重要) 工作流程:核心线程 -> 队列 -> 非核心线程 -> 拒绝策略
  1.当一个新任务被提交(execute())时:

  2.如果 当前运行线程数 < corePoolSize,则立即创建新核心线程运行任务。

  3.如果 当前运行线程数 >= corePoolSize,则尝试将任务放入工作队列。

  4.如果 队列未满,任务入队成功,等待线程空闲后执行。

  5.如果 队列已满,则检查当前线程数是否 < maximumPoolSize。

  6.如果 是,则创建新的非核心线程立即执行这个新任务。

  7.如果 否(即线程数已达最大值),则触发拒绝策略 handler 来处理这个任务。
关键点:创建新线程的时机是:1)核心线程未满时,来任务就创建;2)核心线程已满且队列已满,但总线程数未达最大值时。

 

三:

newFixedThreadPool
newCachedThreadPool
newSingleThreadExecutor
newScheduledThreadPool

newFixedThreadPool:

  特点:固定大小的线程池,核心线程数 = 最大线程数。使用无界的工作队列 (LinkedBlockingQueue)。

  风险:如果任务提交速度远大于处理速度,会导致队列中堆积大量任务,可能引起内存溢出 (OOM)。

  适用场景:适用于负载较重的服务器,需要限制当前线程数量。

newCachedThreadPool:

  特点:核心线程数为 0,最大线程数为 Integer.MAX_VALUE。使用 SynchronousQueue。空闲线程存活时间为 60 秒。

  工作机制:有新任务则创建新线程执行;有空闲线程则复用空闲线程。线程空闲一段时间后会被回收。

  风险:理论上可以无限创建线程,可能耗尽 CPU 和内存资源。

  适用场景:执行很多短期异步的小程序,或负载较轻的服务器。

newSingleThreadExecutor:

  特点:只有一个线程的线程池。使用无界工作队列。能保证所有任务按提交顺序执行(FIFO, LIFO? 取决于队列)。

  风险:同 newFixedThreadPool,有无界队列的 OOM 风险。

  适用场景:需要保证任务顺序执行的场景。

newScheduledThreadPool:

  特点:用于执行定时或周期性任务。核心线程数由参数指定,最大线程数为 Integer.MAX_VALUE。使用特殊的 DelayedWorkQueue。

  注意:在阿里巴巴 Java 开发手册中,强制不允许使用 Executors 创建线程池,而是推荐直接使用 ThreadPoolExecutor 的构造方法,
  目的是让开发者明确线程池的运行规则,规避资源耗尽的风险。

 

四:

合理配置线程池参数
  这是一个经验性的问题,需要考虑任务类型:

    CPU 密集型任务:任务主要消耗 CPU 资源。

      建议:线程数设置为 CPU核心数 + 1。设置过多线程会导致频繁的线程上下文切换,降低效率。

    IO 密集型任务:任务大部分时间在等待 IO 操作(如网络请求、数据库读写)。

      建议:线程数可以设置得多一些,因为 CPU 在等待 IO 时可以执行其他任务。

      参考公式:线程数 = CPU核心数 * (1 + 平均等待时间 / 平均计算时间)。如果等待时间远大于计算时间,可以设置 2 * CPU核心数 或更多。

    实际应用中:需要通过压测来找到最佳参数。可以使用 Runtime.getRuntime().availableProcessors() 获取 CPU 核心数。

 

posted @ 2025-09-24 11:28  新页春秋  阅读(8)  评论(0)    收藏  举报