ThreadLocal——线程本地变量

常见问题

一、ThreadLocal是什么?为什么要使用ThreadLocal

ThreadLocal——线程本地变量。一种用空间换时间的方式,把上锁替换成本地变量。
我们创建一个ThreadLocal变量,那么访问这个变量的每个线程都会有这个变量的一个本地拷贝,多个线程操作这个变量的时候,实际是在操作自己本地内存里面的变量,从而起到线程隔离的作用,避免了并发场景下的线程安全问题。

二、一个ThreadLocal的使用案例

@Test
    public void testTreadLocalSetAndGet(){
        // 提供一个ThreadLocal对象
        ThreadLocal tl = new ThreadLocal();

        // 开启两个线程
        new Thread(()->{
            tl.set("萧焱");
            System.out.println(Thread.currentThread().getName()+":"+tl.get());
            System.out.println(Thread.currentThread().getName()+":"+tl.get());
            System.out.println(Thread.currentThread().getName()+":"+tl.get());
        },"蓝色").start();

        new Thread(()->{
            tl.set("药尘");
            System.out.println(Thread.currentThread().getName()+":"+tl.get());
            System.out.println(Thread.currentThread().getName()+":"+tl.get());
            System.out.println(Thread.currentThread().getName()+":"+tl.get());
        },"绿色").start();
    }

在这里插入图片描述

三、ThreadLocal的原理

  • 每个线程都有一个 属于自己的ThreadLocalMap(ThreadLocal内部类),Map 中元素的键为 ThreadLocal,而值对应线程的变量副本。Map 是数组实现,使用线性探测解决hash冲突,需要手动调用set、get、remove防止内存泄漏。
  • 一个线程内可以存在多个 ThreadLocal 对象。所以其实是 ThreadLocal 内部维护了一个 Map ,这个 Map 不是直接使用的 HashMap ,而是 ThreadLocal 实现的一个叫做 ThreadLocalMap 的静态内部类。
  • 每个线程有唯一的一个threadLocalMap。ThreadLocalMap内部维护着Entry数组,每个Entry代表一个完整的对象,ThreadLocal对象存储为key,”线程局部变量”为value,所以一个线程下可以保存多个”线程局部变量”
  • ThreadLocal适合作为线程上下文变量,简化线程内传参,实现线程隔离
    在这里插入图片描述

四、为什么会导致内存泄漏呢?是因为弱引用吗?

  • 什么是内存泄漏?
    在ThreadLocal中内存泄漏是指ThreadLocalMap中的Entry中的key为null,而value不为null。因为key为null导致value一直访问不到,而根据可达性分析导致在垃圾回收的时候进行可达性分析的时候,value可达从而不会被回收掉,但是该value永远不能被访问到,这样就存在了内存泄漏。
  • 怎么解决?
    对应的 value 在下一次 ThreadLocalMap 调用 set、get、remove 方法时被清除,但是这几个方法需要被显式调用。

五、Key为什么要设计成弱引用呢?强引用不行?

key如果是强引用会导致线程不被回收,key对应ThreadLocal也不被回收,所以要改为弱引用。至于value一定是强引用,所以必须用完调用remove方法。

六、ThreadLocal的应用场景和使用注意点

ThreadLocal的很重要一个注意点,就是使用完,要手动调用remove()
而ThreadLocal的应用场景主要有以下这几种:

  • 使用日期工具类,当用到SimpleDateFormat,使用ThreadLocal保证线性安全
  • 全局存储用户信息(用户信息存入ThreadLocal,那么当前线程在任何地方需要时,都可以使用)√
  • 保证同一个线程,获取的数据库连接Connection是同一个,使用ThreadLocal来解决线程安全的问题
  • 使用MDC保存日志信息。
  • 19
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值