欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

多线程--ThreadLocal和内存泄漏

程序员文章站 2022-03-08 22:37:40
...

ThreadLocal

  • threadlocal是一个线程内部的存储类,可以在指定线程内存储数据,数据存储以后,只有指定线程可以得到存储数据
public class Thread_19_Thread_Local {

    public static class Person{

        Person(String userName){
            this.userName=userName;
        }

        String userName;

        public String getUserName(){
            return userName;
        }


    }

    public static void main(String[] args) {

        ThreadLocal<Person> threadLocal = new ThreadLocal<Person>();

        new Thread(()->{

            try{
                Thread.sleep(2000);
                Person person = threadLocal.get();
                System.out.println("线程二:"+person);
            }catch (Exception e){

            }
        }).start();

        new Thread(()->{

            try{
                Person p = new Person("lhy");
                threadLocal.set(p);
                Person person = threadLocal.get();
                System.out.println("线程一:"+person);
            }catch (Exception e){

            }
        }).start();


    }
}

为什么会这样呢?来see see 源码

多线程--ThreadLocal和内存泄漏

  • 获取当前线程
  • 获取当前线程上的Thread.ThreadLocal.ThreadLocalMap
  • 如果map != null
    • map.set(this,value)
      • key threadLocal
      • value 入参保存值
    • createMap(t,value)
      • 创建一个map保存
        多线程--ThreadLocal和内存泄漏
  • 获取当前线程
  • 获取当前线程上的Thread.ThreadLocal.ThreadLocalMap
  • 如果map != null
    • 以ThreadLocal为key 拿取对应的value
  • 返回一个null

内存泄漏

多线程--ThreadLocal和内存泄漏

代码举例:

ThreadLocal<M> tl = new ThreadLocal<>();
        new Thread(()->{
            tl.set(new Person("lhy"));
            tl.remove();
        }).start();
  • 当方法执行的时候,线程中的 tl 跟方法中的new ThreadLocal() 有引用 引用1
  • 每个线程中有自己的Thread.ThreadLocal.ThreadLocalMap
    • map中key 为 new ThreadLocal() 引用3
    • value 为入参值
  • 如果为引用3 为强引用的话
    • 当方法结束,引用1 断开
    • 但是线程还存在,所有引用3还存在,导致new ThreadLocal()空间还存在
    • 导致内存泄漏

如果为弱引用的话

  • 当方法结束,引用1 断开
  • 由于引用3为弱引用,垃圾回收的时候,就会被回收走
  • 所有 new ThreadLocal() 空间没有引用连接,会被回收

那还存在内存泄漏问题吗?

  • 答案是存在的
  • 虽然方法结束了,引用1 引用3 断开了
  • 但线程存在,ThreadLocal存在,ThreadLocalMap也存在
  • ThreadLocalMap 中的key 为空值, 但value 还指向一块内存地址,没有被回收
  • 所以还存在内存泄漏问题
解决方案
  • 当ThreadLocal使用完成时
  • remove()掉
相关标签: 多线程