赞
踩
首先了解下ThreadLocal的结构
Thread中有成员变量ThreadLocalMap,ThreadLocalMap的key是ThreadLocal,ThreadLocalMap的value是被弱引用WeakReference修饰的对象
源码代码如下:
这个ThreadLocalMap(threadLocals)其实是线程Thread中的一个变量
看到这里其实就好理解了
为什么会发生内存泄漏?
Threadlocal里面使用了一个存在弱引用的ThreadLocalMap,key是ThreadLocal,而value的引用是一个弱引用。
当线程(Thread)被回收时候只有ThreadLocalMap的key(ThreadLocal)被回收,而ThreadLocalMap对应value(ThreadLocalMap.Entry)的由于被弱引用修饰不会被回收,所以回收后ThreadLocalMap的key就变成了null,但value中却还有值。由于只有创建的value的线程可以访问这些缓值,但创建的线程已经被回收掉了,而其他线程永远访问不到这值,这时候就产生了垃圾对象,从而造成内存泄漏
解决方法:
1.使用完毕后及时调用ThreadLocal.remove() (局部变量 中使用调用remove方法,本质就是找到Entry中key为null的数据然后清除)
2.把ThreadLocal设置为全局变量,使得它无法被GC回收(如果在 成员变量 中使用就将修饰符设置为public static,ThreadLocal不会被回收也就不会存在key为null的情况, 也就不会内存泄漏)
附:
(解释:Java中的静态变量不会被垃圾回收器回收。public static静态变量是与类相关联的,而不是与类的实例相关联的,它们存储在方法区中,而不是堆内存中。垃圾回收器只会回收堆内存中不再被引用的对象,而不会回收方法区中的对象。)
java中的全局变量是由public修饰的static成员变量,形如public static int ID;
java中的全局变量是放在静态方法区中的,所有的实例对象会共享同一份全局变量。所以一旦对某个类实例化后对其中的全局变量做出修改,那么其他的实例其中的全局变量值也相应的会被修改。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。