ThreadLocal

发布时间 2023-06-09 00:01:26作者: 帅气的涛啊

介绍

ThreadLocal 提供线程局部变量,ThreadLocal实例通常是线程私有静态字段,使用的目的是希望将线程与状态关联起来。与JMM中局部变量有几分相似之处,但是不用写回主内存(如果违反,那就线程不安全),Thread用完要remove(),特别在线程池的情况下,会出现内存泄漏。

Thread、ThreadLocal、ThreadLocalMap


ThreadLocal.ThreadLocalMap 各自线程拥有自己的Map。

  • 注意???
    思考:为什么要在线程中使用ThreadLocalMap?为什么是Entry数组
    因为一个线程可以拥有多个ThreadLocal,没错,多个ThreadLocal变量。

强、软、弱、虚


强引用:普通对象引用。

Student a=new Student();
a=null;

软引用:内存足够时保留,内存不够时会回收
弱引用:只要gc就回收
虚引用:在对象回收后进行通知,放入引用队列。

什么是内存泄漏?

不再会被使用的对象,不能被回收。

为什么会出现内存泄漏?

key是弱引用,被回收后,value没有被回收。

threadLocalMap使用ThreadLocal的弱引用作为key,如果一个ThreadLocal不存在外部强引用时,Key(ThreadLocal)势必会被GC回收,这样就会导致ThreadLocalMap中key为null, 而value还存在着强引用,只有thead线程退出以后,value的强引用链条才会断掉。
但如果当前线程再迟迟不结束的话,这些key为null的Entry的value就会一直存在一条强引用链:

Thread Ref -> Thread -> ThreaLocalMap -> Entry -> value

永远无法回收,造成内存泄漏。

仔细想想,ThreadLocal 下面这个设计值得学习

  1. Thead 线程中有ThreadLocalMap
  2. 在线程内创建ThreadLocal会自动放进ThreadLocalMap
        ThreadLocal<String> threadLocal = new ThreadLocal<>();
        threadLocal.set("123");
    public void set(T value) {
        Thread t = Thread.currentThread();
        ThreadLocalMap map = t.threadLocals;
        if (map != null) {
            map.set(this, value);
        } else {
            createMap(t, value);
        }
    }