美文网首页
ThreadLocal原理解析

ThreadLocal原理解析

作者: 后来丶_a24d | 来源:发表于2019-10-24 14:03 被阅读0次

    目录

    目录.png

    简介

    • 每个Thread都持有一个ThrealLocal静态变量,ThreadLocal的实现是这样的:每个Thread 维护一个 ThreadLocalMap 映射表,这个映射表的 key 是 ThreadLocal实例本身,value 是真正需要存储的 Object。

    get()方法源码

     public T get() {
            //1、获取当前线程
            Thread t = Thread.currentThread();
            //2、 获取当前线程的ThreadLocalMap 对象
            ThreadLocalMap map = getMap(t);
            if (map != null) {
                //3、map不为空,则以当前 ThreadLocal 对象实例作为key值,去map中取值,有找到直接返回
                ThreadLocalMap.Entry e = map.getEntry(this);
                if (e != null) {
                    @SuppressWarnings("unchecked")
                    T result = (T)e.value;
                    return result;
                }
            }
            //4. map 为空或者在map中取不到值,那么走这里,返回默认初始值, 如果涉及null key会清理以防止内存泄露
            return setInitialValue();
        }
    

    set() 方法源码

    public void set(T value) { 
            //1. 取当前线程对象
            Thread t = Thread.currentThread();
            //2. 取当前线程的数据存储容器
            ThreadLocalMap map = getMap(t);
            if (map != null)
            //3. 如果map不为空,以当前ThreadLocal实例对象为key,存值
                map.set(this, value);
            else
            //4. 如果map为空,新建一个当前线程的数据存储容器
                createMap(t, value);
        }
    

    ThreadLocal为什么会内存泄漏

    • ThreadLocalMap中的Entry继承WeakReference<ThreadLocal<?>
    static class Entry extends WeakReference<ThreadLocal<?>>
    
    • 如果一个ThreadLocal没有外部强引用(项目中一般都会有强引用来引用它所以不会被错误清理, 假如代码直接置为null即取消强引用)来引用它,那么系统 GC 的时候,这个ThreadLocal势必会被回收,这样一来,ThreadLocalMap中就会出现key为null的Entry,就没有办法访问这些key为null的Entry的value,如果当前线程再迟迟不结束的话,这些key为null的Entry的value就会一直存在一条强引用链:Thread Ref -> Thread -> ThreaLocalMap -> Entry -> value永远无法回收,造成内存泄漏。
    • 其实,ThreadLocalMap的设计中已经考虑到这种情况,也加上了一些防护措施:在ThreadLocal的get(),set(),remove()的时候都会清除线程ThreadLocalMap里所有key为null的value。
    • 项目中每次结束都会清理设置ThreadLocalMap的value(即调用remove方法),调用value相应的clear方法将其clear防止内存泄漏

    ThreadLocalMap中的Entry的key设计成弱引用的原因

    • 现在线程基本都是被复用的,为了防止用户忘记调用remove方法而造成不断的内存堆积

    ThreadLocalMap中的Entry的value是强引用的原因

    • 设置成弱引用的话,可能造成代码里面获取value时为null,因为可能被回收

    参考文献

    相关文章

      网友评论

          本文标题:ThreadLocal原理解析

          本文链接:https://www.haomeiwen.com/subject/ahwrvctx.html