会,这是典型的内存泄漏场景:线程池未关闭导致非守护线程长期驻留、threadlocal 泄漏、关联资源无法释放及 jvm 无法正常退出,最终引发 oom 或进程假死。

会,而且是典型的内存泄漏场景。
线程对象长期驻留堆中
ExecutorService 创建的线程池(如 newFixedThreadPool)默认使用非守护线程。这些线程一旦启动,只要线程池没关闭,就会一直存活——即使空闲、没有任务,也维持在 WAITING 状态。每个线程本身携带栈空间、ThreadLocal 变量、上下文信息等,持续占用堆内存和本地内存。多次重复创建未关闭的线程池(比如 Web 请求中每次 new 一个),线程数线性增长,java.lang.Thread 实例大量堆积,直接导致堆内存耗尽,触发 OutOfMemoryError: unable to create new native thread 或 Java heap space。
关联资源无法释放
线程池若持有外部资源引用(例如数据库连接、文件句柄、缓存对象、第三方 SDK 客户端),这些资源不会自动回收。更隐蔽的是 ThreadLocal 泄漏:线程复用时,未清理的 ThreadLocal 值会随线程长期滞留,尤其在 Spring 等容器环境中,可能持有所属 Bean 的强引用,造成整个对象图无法 GC。
JVM 无法正常退出
主线程结束时,JVM 会等待所有非守护线程终止才退出。未 shutdown 的线程池核心线程默认是非守护线程,会导致应用“假死”——看似运行结束,实际进程仍在后台挂起,资源持续占用。在微服务或批处理场景中,这常表现为容器反复重启、内存持续上涨、监控指标异常。
正确关闭的关键操作
- 调用
shutdown():停止接收新任务,但允许已提交任务完成 - 配合
awaitTermination()等待任务自然结束,避免过早强制中断 - 超时后可选
shutdownNow()尝试中断运行中任务(需确保任务支持中断) - 生产环境优先使用 Spring
@Bean(destroyMethod = "shutdown")或自定义AutoCloseable包装类,避免手动遗漏
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











