ThreadLocal原理

ThreadLocal原理

  1. ThreadLocal对象new出来存放到堆中,ThreadLocal引用是存放在栈里
  1. Thread 类有个 ThreadLocalMap 成员变量,Map的key是Threadlocal 对象,value是你要存放的线程局部变量。

    public void set(T value) {
    //获取当前线程Thread,就是上图画的Thread 引用
    Thread t = Thread.currentThread();
    //Thread类有个成员变量ThreadlocalMap,拿到这个Map
    ThreadLocalMap map = getMap(t);
    if (map != null)
    //this指的就是Threadlocal对象
    map.set(this, value);
    else
    createMap(t, value);
    }

    ThreadLocalMap getMap(Thread t) {
    //获取线程的ThreadLocalMap
    return t.threadLocals;
    }

    void createMap(Thread t, T firstValue) {
    //初始化
    t.threadLocals = new ThreadLocalMap(this, firstValue);
    }

  2. ThreadLocalMap 类的定义在 Threadlocal中。结构与HashMap一样

  3. 使用ThreadLocal后一定手动remove掉 引用ThreadLocal的对象被回收了,由于ThreadLocalMap持有ThreadLocal的弱引用,即使没有手动删除,ThreadLocal也会被回收。value在下一次ThreadLocalMap调用set、get、remove的时候会被清除。

  1. ThreadLocal内存泄漏的根源是:由于ThreadLocalMap的生命周期跟Thread一样长,如果没有手动删除对应key就会导致内存泄漏,而不是因为弱引用。

既然是线程局部变量,那为什么不用线程对象(Thread对象)作为key,这样不是更清晰,直接用线程作为key获取线程变量?

  1. 这样设计会有个问题,比如: 我已经把用户信息存在线程变量里了,这个时候需要新增加一个线程变量,比方说新增用户地理位置信息
  2. 我们ThreadlocalMap 的key用的是线程,再存一个地理位置信息,key都是同一个线程(key一样),会覆盖原来的用户信息。

为什么ThreadLocal中的key设计成WeakReference

复制代码
ThreadLocal<UserInfo> userInfoThreadLocal = new ThreadLocal<>();
userInfoThreadLocal.set(userInfo);
  1. 为了尽大可能的避免内存泄漏
  2. new出的ThreadLocal被userInfoThreadLocal强引用,同时也被ThreadLocalMap的Key弱引用
  3. gc要回收ThreadLocal对象的前提是它只被WeakReference引用
  4. 所以只要ThreadLocal对象如果还被 userInfoThreadLocal(强引用) 引用着,GC是不会回收被WeakReference引用的对象的。
  5. 有些线程会用线程池优化,线程生命周期很长,根据JVM 根搜索算法,一直存在 Thread -> ThreadLocalMap -> Entry(元素)这样一条引用链路,如果key不设计成WeakReference类型,是强引用的话,就一直不会被GC回收,key就一直不会是null,不为null Entry元素就不会被清理(ThreadLocalMap是根据key是否为null来判断是否清理Entry)
  6. 所以ThreadLocal的设计者认为只要ThreadLocal 所在的作用域结束了工作被清理了,GC回收的时候就会把key引用对象回收,key置为null,ThreadLocal会尽力保证Entry清理掉来最大可能避免内存泄漏。
  7. ThreadLocalMap中Entry 继承了WeakReference类,Entry 中的 key 是WeakReference类型的,在Java 中当对象只被 WeakReference 引用,没有其他对象引用时,被WeakReference 引用的对象发生GC 时会直接被回收掉。
相关推荐
m0_736919104 小时前
C++代码风格检查工具
开发语言·c++·算法
yugi9878384 小时前
基于MATLAB强化学习的单智能体与多智能体路径规划算法
算法·matlab
Coder_Boy_4 小时前
技术让开发更轻松的底层矛盾
java·大数据·数据库·人工智能·深度学习
helloworldandy4 小时前
使用Pandas进行数据分析:从数据清洗到可视化
jvm·数据库·python
DuHz4 小时前
超宽带脉冲无线电(Ultra Wideband Impulse Radio, UWB)简介
论文阅读·算法·汽车·信息与通信·信号处理
invicinble4 小时前
对tomcat的提供的功能与底层拓扑结构与实现机制的理解
java·tomcat
Polaris北极星少女4 小时前
TRSV优化2
算法
较真的菜鸟4 小时前
使用ASM和agent监控属性变化
java
黎雁·泠崖5 小时前
【魔法森林冒险】5/14 Allen类(三):任务进度与状态管理
java·开发语言
代码游侠5 小时前
C语言核心概念复习——网络协议与TCP/IP
linux·运维·服务器·网络·算法