主题
面试速答(先看这里)
**一句话结论:**其实这个问题就是上面这个问题的变形。
60秒标准回答:
其实这个问题就是上面这个问题的变形。( 请仔细看上面这篇文章之后再学习本文,不然可能看不懂。 )
如果在线程池中使用ThreadLocal,线程就要复用,就不会被销毁,ThreadLocal 变量不会自动清理,容易造成内存泄漏!
因为 ThreadLocal 绑定在线程的 ThreadLocalMap 里。如上图的引用链。如果线程一直被复用,那么Thread Ref就会一直在,那么他关联的Thread对象,ThreadLocalMap和其中的Value就会一直在,无法被回收
**答题顺序:**结论 → 原理/机制 → 关键流程 → 场景与取舍 → 易错点
回答主线:
- **要点1:**如果在线程池中使用ThreadLocal,线程就要复用,就不会被销毁,ThreadLocal 变量不会自动清理,容易造成内存泄漏!
- **要点2:**因为 ThreadLocal 绑定在线程的 ThreadLocalMap 里。
- **要点3:**随着线程不断服用,不断的往ThreadLocalMap中加东西,就会导致Value越来越多。
- **要点4:**ThreadLocalMap底层使用数组来保存元素,使用“线性探测法”来解决hash冲突的,在每次调用ThreadLocal的get、set、remove等方法的时候,内部会实际调用ThreadLocalMap的get、set、remove等操作。
- **要点5:**而ThreadLocalMap的每次get、set、remove,都会清理key为null,但是value还存在的Entry。
**记忆锚点:**ThreadLocalMap → ThreadLocal → remove → get → set → Thread
易错提醒:
- ) 如果在线程池中使用ThreadLocal,线程就要复用,就不会被销毁,ThreadLocal 变量不会自动清理,容易造成内存泄漏!
加分表达:
- 如果线程一直被复用,那么Thread Ref就会一直在,那么他关联的Thread对象,ThreadLocalMap和其中的Value就会一直在,无法被回收。
- (装B时刻:现在是2025年9月19日,JDK25在两天前发布了,新出了一个ScopedValue,可以解决这个内存泄漏的问题,你如果面试的时候主动提一句,会让面试官觉得你很有技术热情。
追问准备:
- 围绕「ThreadLocalMap」:底层原理是什么?使用时有哪些边界和常见坑?
- 围绕「ThreadLocal」:底层原理是什么?使用时有哪些边界和常见坑?
- 围绕「remove」:底层原理是什么?使用时有哪些边界和常见坑?
- 如果线上出现异常,你会如何定位、验证并规避?
典型回答
📄 ✅ThreadLocal为什么会导致内存泄漏?如何解决的?
打开文档:✅ThreadLocal为什么会导致内存泄漏?如何解决的?
其实这个问题就是上面这个问题的变形。(请仔细看上面这篇文章之后再学习本文,不然可能看不懂。)
如果在线程池中使用ThreadLocal,线程就要复用,就不会被销毁,ThreadLocal 变量不会自动清理,容易造成内存泄漏!

因为ThreadLocal 绑定在线程的 ThreadLocalMap 里。如上图的引用链。如果线程一直被复用,那么Thread Ref就会一直在,那么他关联的Thread对象,ThreadLocalMap和其中的Value就会一直在,无法被回收。
随着线程不断服用,不断的往ThreadLocalMap中加东西,就会导致Value越来越多。最终导致OOM。
ThreadLocalMap底层使用数组来保存元素,使用“线性探测法”来解决hash冲突的,在每次调用ThreadLocal的get、set、remove等方法的时候,内部会实际调用ThreadLocalMap的get、set、remove等操作。
而ThreadLocalMap的每次get、set、remove,都会清理key为null,但是value还存在的Entry。
所以,当我们在一个ThreadLocal用完之后,手动调用一下remove,就可以在下一次GC的时候,把Entry清理掉。
(装B时刻:现在是2025年9月19日,JDK25在两天前发布了,新出了一个ScopedValue,可以解决这个内存泄漏的问题,你如果面试的时候主动提一句,会让面试官觉得你很有技术热情。很加分!!!)
📄 ✅JDK25的ScopedValue是什么?为什么可以替代ThreadLocal?
打开文档:✅JDK25的ScopedValue是什么?为什么可以替代ThreadLocal?