java封装好的线程池
📅 2026/7/5 2:59:11
👁️ 阅读次数
📝 编程学习
Java 中封装好的线程池主要通过Executors工具类来创建,底层均是基于ThreadPoolExecutor类实现的。常见的有以下几种:
固定大小线程池 (
newFixedThreadPool)
创建一个固定长度的线程池,可以控制最大并发数。当线程都在忙时,新提交的任务会进入等待队列,直到有空闲线程。可缓存线程池 (
newCachedThreadPool)
创建一个可根据需要创建新线程的线程池。如果线程池的当前规模超过了处理需求,它会灵活地回收空闲线程;如果没有可回收的线程,则会创建新线程。单线程线程池 (
newSingleThreadExecutor)
创建一个单线程化的线程池,它只会使用唯一的工作线程来执行任务,保证所有任务按照指定顺序(如 FIFO)执行。定时任务线程池 (
newScheduledThreadPool)
创建一个固定长度的线程池,支持定时及周期性任务的执行。
但是在生产环境中,强烈不推荐直接使用Executors工具类提供的这四种线程池(newFixedThreadPool、newCachedThreadPool、newScheduledThreadPool、newSingleThreadExecutor),原因:
为什么不推荐?各线程池的致命隐患如下:
- newFixedThreadPool 与 newSingleThreadExecutor
- 隐患:底层使用了无界的
LinkedBlockingQueue(容量默认为Integer.MAX_VALUE)。当任务提交速度大于处理速度时,任务会无限堆积,最终耗尽 JVM 堆内存,导致OutOfMemoryError。
- 隐患:底层使用了无界的
- newCachedThreadPool
- 隐患:最大线程数被设置为
Integer.MAX_VALUE,且使用不缓冲的SynchronousQueue。在突发高并发流量下,它会无节制地创建海量线程,瞬间耗尽线程栈内存或导致 CPU 频繁上下文切换,引发系统假死或宕机。线程数失控导致 OOM。
- 隐患:最大线程数被设置为
- newScheduledThreadPool
- 隐患:底层使用的是无界的延迟队列
DelayedWorkQueue。如果调度任务执行缓慢或发生阻塞,后续所有的延时任务都会持续积压在队列中,同样存在内存泄漏和 OOM 的风险。
- 隐患:底层使用的是无界的延迟队列
生产环境的正确做法
在生产环境中,必须绕过Executors工厂类,手动构造ThreadPoolExecutor,显式配置所有核心参数,确保资源边界可控:
- 核心与最大线程数:根据业务是 CPU 密集型还是 IO 密集型,合理设置
corePoolSize和maximumPoolSize。 - 有界队列:必须使用有界阻塞队列(如
ArrayBlockingQueue),并明确指定容量上限,防止任务无限堆积。 - 拒绝策略:显式配置拒绝策略(如
CallerRunsPolicy),在队列满时提供缓冲或快速失败机制,防止系统雪崩。 - 自定义线程工厂:为线程设置有业务含义的名称(如
order-async-%d),便于在排查日志和进行线程 Dump 时快速定位问题归属。 - 专用定时线程池:对于定时/周期任务,应直接
new ScheduledThreadPoolExecutor(...)并显式指定核心线程数,避免单点故障。
编程学习
技术分享
实战经验