Java ThreadLocal源码总结 ThreadLocal源码注释翻译和解析中英文对照版

版本
JDK8(JDK1.8)

ThreadLocal类源码重点
1.ThreadLocal类是用于创建线程私有变量的类,其原理是,在每个Thread类中都有一个ThreadLocalMap类,就是一个Hash表,而这个ThreadLocalMap以ThreadLocal为键,以线程私有变量为值,又由于每个Thread对象的ThreadLocalMap都不同,所以虽然只有同一个ThreadLocal对象,也可以在不同的线程中对应不同的值

2.从ThreadLocal的get方法就可以知道,为什么不同线程调用同一个ThreadLocal对象的get方法返回的值可以不一样,
因为get()方法一直获取的是当前线程中的ThreadLocalMap,不同线程的ThreadLocalMap是不一样的

public T get() {
   
        // 获得当前运行线程
        Thread t = Thread.currentThread();
        // 取出当前线程内部的 ThreadLocalMap
        ThreadLocalMap map = getMap(t);
        // 如果线程内部的 ThreadLocalMap不为空
        if (map != null) {
   
            // 以当前ThreadLocal对象为为键,取出<ThreadLocal, Object>键值对
            ThreadLocalMap.Entry e = map.getEntry(this);
            // 如果键值对不为空
            if (e != null) {
   
                @SuppressWarnings("unchecked")
                // 取出键值对中的值
                T result = (T)e.value;
                return result;
            }
        }
       // 如果线程内部的 ThreadLocalMap为空,调用设置并获取初始值的方法
        return setInitialValue();
    }

注: 从上面可以看出ThreadLocalMap是惰性创建的,只有在使用ThreadLocal的get()、set()这些方法时才会尝试创建ThreadLocalMap,初始化代码如下

 private T setInitialValue() {
   
        // 获取初始值
        T value = initialValue();
        // 获取当前线程
        Thread t = Thread.currentThread();
        // 取出当前线程中的ThreadLocalMap
        ThreadLocalMap map = getMap(t);
        // 如果ThreadLocalMap不为空,则以当前ThreadLocal对象为键,初始值为值
        // 将该键值对添加进ThreadLocalMap
        if (map != null) {
   
            map.set(this, value);
        } 
        // 如果ThreadLocalMap为空
        else {
   
            // 创建 ThreadLocalMap对象
            createMap(t, value);
        }
        // 如果该ThreadLocal对象原先属于TerminatingThreadLocal类或其子类
        if (this instanceof TerminatingThreadLocal) {
   
            // 则将其添加到Collection<TerminatingThreadLocal<?>> 中
            // 用于线程结束时释放TerminatingThreadLocal<?>中的?资源
            TerminatingThreadLocal.register((TerminatingThreadLocal<?>) this);
        }
        // 返回初始值
        return value;
    }

3.ThreadLocal内存泄漏问题,因为ThreadLocalMap是由一个Entry数组实现的,Entry就是一个键值对类,如下,

static class Entry extends WeakReference<ThreadLocal<?>> {
   
            /** The value associated with this ThreadLocal.
             * 与此ThreadLocal关联的值。
             */
            Object value;

            // 内存泄漏,ThreadLocal被GC回收了为null,则无法通过null取出value,
            // 可以通过expungeStaleEntry回收键为null的Entry
            Entry(ThreadLocal<?> k, Object v) {
   
                // 键是弱引用,逃不过一次GC收集,软引用直到空间不足才回收
                // 为什么设为弱引用,因为ThreadLocal一开始都会有强引用,
                // 如果不想要了,设为null,则想GC收集它,如果不设为弱引用,则一直无法回收
                super(k);
                // 值是强引用,因为不清楚这个值会不会还有其他强引用,
                // 如果没有,若设置为弱引用,则取出的值可能是null
                value = v;
            }
        }

内存泄漏原因:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

lolxxs

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值