ThreadLocal在什么情况下会导OOM?
(金石计划火热进行中,速戳上图了解)ThreadLocal本身设计上是为了解决线程之间共享变量带来的并发问题,但使用不当时,「确实可能导致内存泄露甚至最终导致 OutOfMemoryError(OOM)」。下面是具体可能导致 OOM 的几种情况:
一、根本原因:「ThreadLocalMap 的 Entry 是弱引用,但 value 是强引用」在ThreadLocal的底层实现中,每个线程 (Thread) 都维护一个ThreadLocalMap,其 key 是ThreadLocal对象的「弱引用」,value 是实际存储的对象,「强引用」。
弱引用的影响:如果你没有保存对ThreadLocal实例的强引用,GC 后它可能会被回收,但其对应的value仍然存在,「ThreadLocalMap 里的 entry 的 key 就变成了 null,但 value 还在,导致内存泄露」。
二、常见导致 OOM 的场景场景 1:线程池 + ThreadLocal 使用不当线程池中的线程是「长期存活」的;如果使用完ThreadLocal后不调用remove(),它的 value 会一直保留在线程中,不能被回收;如果这个 value 是大对象(如数据库连接、缓存、List 等),会导致内存不断积累;长时间运行后,堆内存爆满,抛出OutOfMemoryError: Java heap space。?「典型例子」:在 Web 应用中,使用线程池处理请求并使用ThreadLocal缓存用户信息或数据库连接等大对象。
?场景 2:频繁创建 ThreadLocal 实例,没有 remove() 清理每次请求都新建一个ThreadLocal对象,丢弃引用不调用remove(),GC 后 key 被清除但 value 还在,时间久了堆积大量无法访问的对象,也会造成 OOM。
三、解决建议? 正确使用方式ThreadLocalMyObject threadLocal =newThreadLocal();
try{
threadLocal.set(newMyObject());
// do something
}finally{
threadLocal.remove();// 避免内存泄漏
}
? 使用InheritableThreadLocal或TransmittableThreadLocal时更要小心它们可能在跨线程传递 ThreadLocal 时保留引用,清理不及时也可能导致内存泄漏。
四、总结问题原因是否易复现是否能导致 OOM使用线程池后未调用remove()??未持有 ThreadLocal 实例引用??(内存泄漏但未必 OOM)每次创建新 ThreadLocal 且未清理??value 是大对象??AI编程资讯AI Coding专区指南:
https://aicoding.juejin.cn/aicoding
点击"阅读原文"了解详情~
阅读原文
网站开发网络凭借多年的网站建设经验,坚持以“帮助中小企业实现网络营销化”为宗旨,累计为4000多家客户提供品质建站服务,得到了客户的一致好评。如果您有网站建设、网站改版、域名注册、主机空间、手机网站建设、网站备案等方面的需求...
请立即点击咨询我们或拨打咨询热线:13245491521 13245491521 ,我们会详细为你一一解答你心中的疑难。 项目经理在线