弄清ThreadLocal 原理

场景

主要用在多线程场景里,把某个变量设置在线程中,不能被其他线程访问到,保证变量线程安全。如:session管理 ,事务管理,日志输出等等。

源码分析

ThreadLocal 主要提供 有无参数构造方法、set、get、remove方法。无参构造方法中没有代码,说明new的时候没有逻辑。主要看set方法

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

先获取当前线程对象,再创建ThreadLocalMap。注意看createMap方法中把ThreadLocalMap对象绑在了线程对象的变量上了。这里才是变量隔离的根本原因,可以看出ThreadLocal本省就像一个工具类。ThreadLocalMap 就是存放数据的地方,类似map,实现类是继承WeakReference的Entry类,WeakReference代表弱应用对象,主要把key进行弱引用,value是强引用的。

get方法、remove方法比较简单。

使用对象关系图:
在这里插入图片描述

弱引用

一些博客可能理解不太正确,key弱引用为了value能够被GC回收,否则回收不了,防止内存溢出。
其实key弱引用和value没有关系,由上图可以分析出 主要为了GC能够回收threadLocal对象,前提是threadLocal没有被其他地方引用。threadLocal可以被多次new的,如果不设置弱引用的话,会一直被线程对象引用造成内存泄漏。
这里注意下如果threadLocal被回收那么ThreadLocalMap 中就会出现key 为null的Entry。如果不做remove()方法,value 永远无法被GC 回收,这个时候就也可能会产生内存泄露,前提线程对象一直存在。所以value对象能不能被回收最终要看有么有调用remove方法的和弱引用没有关系。
还有调用set,get,remove方法都会清空key 为null的Entry的对象,也是保证value能够被回收。

个人理解

  1. 在实际开发应用中通常吧theadLocal在程序启动的时候设置成final static ,所以这里的弱引用其实没有效果,不会被回收的。(弱应用只有面试会被问到)
  2. 为了安全起见用完一定要调用remove方法,才能保证value被回收,如果线程被共用的话会拿到旧数据。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值