ThreadLocal内存泄漏问题

ThreadLocal实现变量的访问隔离原理是在每个线程的内部维护了一个ThreadLocalMap类型的变量,这个变量的key就是该ThreadLocal(弱引用类型),值就是每个线程存储的值。从ThreadLocal获取值的时候,是先获取当前运行的线程,从而获取到当前线程的ThreadLocalMap变量,根据key获取到当前线程的值。设置和移除的操作类似。

ThreadLocal造成内存泄漏的原因就在于,ThreadLocalMap的存活时间和当前线程的存活时间一样长,由于ThreadLocalMap的key是弱引用,所有有GC的时候就会被回收,而如果此时当前线程的生命周期还没有结束,那么就会出现ThreadLocalMap中的某个Entry的key为null,value不为null的情况。调用链如上图(盗用别人的图):current-ThreadRef——》currentThread——》ThreadLocalMap——》Entry一直存在,这就造成了内存泄漏。

为了避免内存泄漏,最好在每次使用完ThreadLocal后调用其remove()将数据清除掉。

在java8中,

ThreadLocalMap 的 set 方法通过调用 replaceStaleEntry 方法回收键为 null 的 Entry 对象的值(即为具体实例)以及 Entry 对象本身从而防止内存泄漏

get方法会间接调用 expungeStaleEntry 方法将键和值为 null 的 Entry 设置为 null 从而使得该 Entry 可被回收

你可能感兴趣的:(java)