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 时会直接被回收掉。
相关推荐
码农小河6625 分钟前
基于SSM+JSP的高校专业信息管理系统【附源码+数据库】
java·开发语言·数据库
其实防守也摸鱼2 小时前
个人学习 Pwn 思路:从基础到漏洞利用的进阶路径
大数据·前端·人工智能·chrome·算法·安全·网络安全
风若飞3 小时前
Spring Ai 入门遇到问题1
java·后端·spring
Nuanyt3 小时前
LeetCode Hot 100 链表专题(五)· 2 题(Java)
java·算法·leetcode·链表
黑马程序员毕设4 小时前
基于 Java 的餐饮点餐系统设计与应用报告
java·开发语言
SL_staff4 小时前
从文档工具到知识中枢:基于JVS数字底座构建企业级统一内容管理平台的技术实践
java·开源·全栈
SL_staff4 小时前
从‘连得上’到‘管得好’:JVS-IOT双引擎驱动设备运维闭环
java·物联网·产品
w_zero_one6 小时前
递归算法(一)
java·开发语言·算法
SL_staff6 小时前
私有化低代码不是减配版开发:JVS双模式建模如何重建IT交付信任
java·低代码·spring cloud