参考:Java线程池实现原理及其在美团业务中的实践 - 美团技术团队

线程池核心参数

  1. 核心线程数corePoolSize
    如果项目有固定的线程开销可以使用核心线程
  2. 最大线程maximumPoolSize
    如果项目中多线程的场景不是很多,将线程池中的线程全部设置为普通线程,用完后就释放,减少资源占用
  3. 工作队列workQueue
    指定有界或无界队列,队列长度,一般我们选择有界队列,无界队列容易导致OOM

场景一:快速响应用户请求

场景:需要快速响应的场景,如首屏加载、商品详情页加载这种越快越好的场景

应该不设置队列去缓冲并发任务,而是调高corePoolSizemaxPoolSize去尽可能创造多的线程快速执行任务。

场景2:快速处理批量任务

描述:离线的大量计算任务,需要快速执行。比如说,统计某个报表,需要计算出全国各个门店中有哪些商品有某种属性,用于后续营销策略的分析,那么我们需要查询全国所有门店中的所有商品,并且记录具有某属性的商品,然后快速生成报表。

分析:这种场景需要执行大量的任务,我们也会希望任务执行的越快越好。这种情况下,也应该使用多线程策略,并行计算。但与响应速度优先的场景区别在于,这类场景任务量巨大,并不需要瞬时的完成,而是关注如何使用有限的资源,尽可能在单位时间内处理更多的任务,也就是吞吐量优先的问题。所以应该设置队列去缓冲并发任务,调整合适的corePoolSize去设置处理任务的线程数在这里,设置的线程数过多可能还会引发线程上下文切换频繁的问题,也会降低处理任务的速度,降低吞吐量。

总结

考虑到在实际应用中我们获取并发性的场景主要是两种:

  1. 并行执行子任务,提高响应速度。这种情况下,应该使用同步队列,没有什么任务应该被缓存下来,而是应该立即执行
  2. 并行执行大批次任务,提升吞吐量。这种情况下,应该使用有界队列,使用队列去缓冲大批量的任务,队列容量必须声明,防止任务无限制堆积。所以线程池只需要提供这三个关键参数的配置,并且提供两种队列的选择,就可以满足绝大多数的业务需求,Less is More