ThreadLocal原理及内存泄漏分析
介绍
每个线程内部都有一个私有的 ThreadLocalMap
实例,用于存储该线程关联的所有 ThreadLocal 变量。 ThreadLocalMap
内部的 Entry
继承自 WeakReference<ThreadLocal<?>>
。所以**Entry
的 key
(即 ThreadLocal 对象本身)是通过弱引用指向的**。
Entry 中的 value 字段始终保持着对实际存储值的强引用。
内存泄漏问题分析
当一个 ThreadLocal 对象(也就是key
)在应用程序中不再被任何强引用指向时(例如,声明它的类实例被回收,或者局部变量超出作用域),在下一次垃圾回收(GC)时,这个弱引用 会被回收此即GC 会回收这个 ThreadLocal
对象,Entry
中的 key
会变为 null
。但是value被 Entry
强引用着,只要线程不死,当前线程ThreadLocalMap的Entry一直强引用者value。假设是长期存活的线程池中的线程,这种泄漏可能会不断累积,最终可能导致 OutOfMemoryError
。
防止内存泄漏方法:
- 在使用完毕后调用
ThreadLocal.remove()
,remove()
放在finally
块中执行,确保无论代码逻辑是否发生异常都能清理资源。 - 将 ThreadLocal 定义为
private static final
,这本身不会导致泄漏(ThreadLocal因为强引用在类上),用完之后必须主动remove