为什么不建议使用Executors创建线程池?
JDK为我们提供了Executors线程池工具类,里面有默认的线程池创建策略,大概有以下几种:
-
FixedThreadPool:线程池线程数量固定,即corePoolSize和maximumPoolSize数量一样。
-
SingleThreadPool:单个线程的线程池。
-
CachedThreadPool:初始核心线程数量为0,最大线程数量为Integer.MAX_VALUE,线程空闲时存活时间为60秒,并且它的阻塞队列为SynchronousQueue,它的初始长度为0,这会导致任务每次进来都会创建线程来执行,在线程空闲时,存活时间到了又会释放线程资源。
-
ScheduledThreadPool:创建一个定长的线程池,而且支持定时的以及周期性的任务执行,类似于Timer。
虽然用Executors工具类方便,但是阿里巴巴开发手册强制不允许使用Executors来创建线程池,原因在于:(摘自阿里编码规约)
线程池不允许使用Executors去创建,而是通过ThreadPoolExecutor的方式,这样的处理方式让写的同学更加明确线程池的运行规则,
规避资源耗尽的风险。说明:Executors各个方法的弊端:newFixedThreadPool和newSingleThreadExecutor: 主要问题是堆积的请
求处理队列可能会耗费非常大的内存,甚至OOM。newCachedThreadPool和newScheduledThreadPool: 主要问题是线程数最大数
是Integer.MAX_VALUE,可能会创建数量非常多的线程,甚至OOM。
我们从JDK源码中寻找一波答案:java.util.concurrent.Executors:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | // FixedThreadPool public static ExecutorService newFixedThreadPool( int nThreads) { return new ThreadPoolExecutor(nThreads, nThreads, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>()); } // SingleThreadPool public static ExecutorService newSingleThreadExecutor() { return new FinalizableDelegatedExecutorService ( new ThreadPoolExecutor( 1 , 1 , 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>())); } // CachedThreadPool public static ExecutorService newCachedThreadPool() { // 允许创建线程数为Integer.MAX_VALUE return new ThreadPoolExecutor( 0 , Integer.MAX_VALUE, 60L, TimeUnit.SECONDS, new SynchronousQueue<Runnable>()); } // ScheduledThreadPool public ScheduledThreadPoolExecutor( int corePoolSize) { // 允许创建线程数为Integer.MAX_VALUE super (corePoolSize, Integer.MAX_VALUE, 0 , NANOSECONDS, new DelayedWorkQueue()); } |
1 2 3 4 | public LinkedBlockingQueue() { // 允许队列长度最大为Integer.MAX_VALUE this (Integer.MAX_VALUE); } |
从JDK源码可看出,Executors工具类无非是把一些特定参数进行了封装,并提供一些方法供我们调用而已,我们并不能灵活地填写参数,策略过于简单,不够友好。
CachedThreadPool和ScheduledThreadPool最大线程数为Integer.MAX_VALUE,如果线程无限地创建,会造成OOM异常。
LinkedBlockingQueue基于链表的FIFO队列,是无界的,默认大小是Integer.MAX_VALUE,因此FixedThreadPool和SingleThreadPool的阻塞队列长度为Integer.MAX_VALUE,如果此时队列被无限地堆积任务,会造成OOM异常。
以上是“为什么不建议使用Executors创建线程池”这篇文章的所有内容,感谢各位的阅读!
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 单元测试从入门到精通
· 上周热点回顾(3.3-3.9)
· Vue3状态管理终极指南:Pinia保姆级教程