原文链接:ThreadLocal为什么会出现内存泄漏,你真的知道吗? – 编程屋
目录
大家想要搞清楚这个问题,就必须知道内存泄漏和内存溢出的区别
内存泄漏:不就被使用的对象或者变量无法被回收
内存溢出:没有剩余的空间来创建新的对象
同一个threadlocal对象,不同线程之间存储的值是获取不到的
- public class QuThreadLocal {
-
- static ThreadLocal
t1 = new ThreadLocal<>(); -
- public static void main(String[] args) {
- new Thread(()->{
- try {
- Thread.sleep(100);
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- t1.set(new Wolf("小王"));
- System.out.println(t1.get());
- t1.remove();
- }).start();
-
-
- new Thread(()->{
- try {
- Thread.sleep(200);
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- System.out.println(t1.get());
- }).start();
- }
- }
可以发现在不同的线程里面放置东西,其它线程里面是找不到的。
解析原因,观察是如何向threadlocal中放置值的:
- public void set(T value) {
- Thread t = Thread.currentThread();
- ThreadLocalMap map = getMap(t);
- if (map != null)
- map.set(this, value);
- else
- createMap(t, value);
- }
- void createMap(Thread t, T firstValue) {
- t.threadLocals = new ThreadLocalMap(this, firstValue);
- }
1)先获取当前线程t,然后根据t获取threadmap对象
2)判断map是否为null,map不为null时,将当前threadllocal对象作为key,想要设置的值作为value放置其中,否则就创建一个map。创建map的key值与上相同。
这也表明了,存储的值只有当前线程才能够获取到。
threadlocal内部结构:
造成内存泄漏的原因:
由于Entry中的value是强引用,key是弱引用;当垃圾回收器回收threadlocal时,由于value是强引用,不能被回收,所以造成了内存泄漏。
因此,ThreadLocal内存泄漏的根源是:由于ThreadLocalMap的生命周期跟Thread一样长,如果没有手动删除对应的key就会导致内存泄漏,而并不是因为弱引用。
解决方案一:扩大成员变量Threadlocal的一个作用域,避免被GC回收(不推荐)
解决方案二:每次使用完threadlocal之后,就调用remove方法去移除对应的数据(推荐)
以上只是部分内容,为了维护方便,本文已迁移到新地址:ThreadLocal为什么会出现内存泄漏,你真的知道吗? – 编程屋