欢迎访问欧博网址!

597金华人才网:Java ThreadLocal剖析

admin3周前6

简介

ThreadLocal 类似局部变量,解决了单个线程维护自己线程内的变量值(存、取、删),让线程之间的数据举行隔离。(InheritableThreadLocal 特例)

这里涉及三个类,Thread、ThreadLocal、ThreadLocalMap

源码剖析

  1. Thread 中有一个 ThreadLocal.ThreadLocalMap 类型的变量 threadLocals。由于ThreadLocalMap变量是跟线程绑定的,以是不存在多线程共享变量之间的并发问题,以是ThreadLocal也就是线程平安的变量。
  2. ThreadLocalMap 是 ThreadLocal 的一个内部静态类,没有继续java.util.Map,界说了一个Entry[]变量,通过Entry的get()方式作为key,value属性作为值来实现一个类似Map的操作
  3. Entry 是 ThreadLocalMap 的一个内部静态类,继续WeakReference<ThreadLocal<?>>,而且界说了一个变量value(Object类型)
  4. ThreadLocal 内部封装了getMap()、Set()、Get()、Remove()4个焦点方式,用于操作ThreadLocalMap
  5. 通过getMap()获取每个子线程Thread持有自己的ThreadLocalMap实例,因此它们是不存在并发竞争的
  6. ThreadLocalMap中Entry[]数组存储数据,初始化长度16,大于即是3/4阈值,就举行2倍扩容。
  7. ThreadLocalMap中Entry的key是对ThreadLocal的弱引用,当主线程甩掉掉ThreadLocal工具时,垃圾收集器会忽略这个key的引用而清算掉ThreadLocal工具, 防止了内存泄露。
  8. 散列算法-魔数0x61c88647,行使一定算法实现了元素的完善散列

看源码可以得出,set、get、remove操作的都是ThreadLocalMap,key为当前线程,value为线程局部变量缓存值

public void set(T value) {
    Thread t = Thread.currentThread();
    ThreadLocalMap map = getMap(t);
    if (map != null)
        map.set(this, value);
    else
        createMap(t, value);
}

public T get() {
    Thread t = Thread.currentThread();
    ThreadLocalMap map = getMap(t);
    if (map != null) {
        ThreadLocalMap.Entry e = map.getEntry(this);
        if (e != null) {
            @SuppressWarnings("unchecked")
            T result = (T)e.value;
            return result;
        }
    }
    return setInitialValue();
}

public void remove() {
    ThreadLocalMap m = getMap(Thread.currentThread());
    if (m != null)
        m.remove(this);
}

ThreadLocalMap getMap(Thread t) {
    return t.threadLocals;
}

问题

不挪用remove会内存溢出吗?
大部分场景下是不会的,少数场景才会。

运行时,会在栈中发生两个引用,指向堆中响应的工具。
可以看到,ThreadLocalMap使用ThreadLocal的弱引用作为key,这样一来,假设当ThreadLocal ref和ThreadLocal之间的强引用断开时,即ThreadLocal ref被置为null,下一次GC时,threadLocal工具势必会被接纳。
这样,ThreadLocalMap中就会泛起key为null的Entry,就没有办法接见这些key为null的Entry的value,若是当前线程再迟迟不竣事的话,好比使用线程池,线程使用完成之后会被放回线程池中,不会被销毁,这些key为null的Entry的value就会一直存在一条强引用链:
Thread Ref -> Thread -> ThreaLocalMap -> Entry -> value永远无法接纳,造成内存泄露。

参考资料

https://www.cnblogs.com/dennyzhangdd/p/7978455.html ThreadLocal最终源码剖析
https://liwx2000.iteye.com/blog/1774169 ThreadLocal会内存溢出吗
https://www.jianshu.com/p/cdb2ea3792b5 深入明白Java弱引用

,

Sunbet

www.ipvps.cn信誉来自于每一位客户的口碑,Sunbet携手江苏安腾科技有限公将致力服务好每位Sunbet会员。!

上一篇 下一篇

猜你喜欢

最新文章
热门文章
热评文章
随机文章
热门标签