ThreadLocal详解

在做项目时发现项目中一般都会把用户信息存入ThreadLocal中,方便后续使用用户信息。但是ThreadLocal的原理是什么呢?这里结合网上的资料记录一下我自己的理解。

ThreadLocal是什么?

网上有的说法是ThreadLocal是线程本地变量,如果创建了一个ThreadLocal变量,那么访问这个变量的每个线程都会有这个变量的一个本地拷贝,多个线程操作这个变量的时候,实际是操作自己本地内存里面的变量,从而起到线程隔离的作用,避免了线程安全问题。
但是我觉得这段话说的不够清楚,甚至有歧义,至少我初看时是理解错了。
实际上这个ThreadLocal就是一个类,用来操作ThreadLocalMap的一个工具类(后面会解释为什么这么说),那这个ThreadLocalMap又是什么呢?
每个Thread线程下面都有一个成员变量threadLocals,可以看到数据类型就是ThreadLocalMap。
在这里插入图片描述
所以并不是每个线程都有一个ThreadLocal,而是每个线程都有一个ThreadLocalMap,而ThreadLocalMap根据这个名字就应该知道具体结构是一个map结构,如下图所示。
在这里插入图片描述
如果有多个用户,即多个线程,情况就是
在这里插入图片描述
可以看到对于ThreadLocalMap每个entry的key就是ThreadLocal变量本身的引用,而value为不同线程下的存入的数据。
并且,可以看出来,不同的线程中有不同的ThreadLocalMap,但是entry中key指向ThreadLocal是同一个,也就是说ThreadLocal是被不同的线程共享的,或许这就是文章开头那段概念中“访问这个变量的每个线程都会有这个变量的一个本地拷贝”的意思?

ThreadLocal如何保证线程隔离?

线程隔离就是指存在这个线程的数据不能被其它线程改变。
以存取用户信息为例子。

  • 创建一个ThreadLocal变量
private static final ThreadLocal<User> threadLocal = new ThreadLocal<>();
  • 存数据。
threadLocal.set(user);

set的具体实现其实是先得到此线程的ThreadLocalMap,然后以threadLocal自身引用为key,user为value,存进ThreadLocalMap。代码如下。
在这里插入图片描述

  • 取数据
threadLocal.get();

get的具体实现也是先获得当前线程的ThreadLocalMap,然后以threadLocal自身引用为key,去ThreadLocalMap中找对应的value。(谁调用的get()谁就是key)
在这里插入图片描述

  • 因为不同线程拥有不同的ThreadLocalMap,所以不同线程的存取数据操作都是在不同的空间的进行的,互不影响。达到线程隔离的效果。其实也就是每个线程开辟了一个自己的独立空间(ThreadLocalMap)存数据,虽然开启空间的钥匙是一样的(ThreadLocal),但是你没办法拿这个钥匙开启我的空间,因为你根本看不到我的空间,没有访问我的空间的机会。
  • 可以看出来,threadLocal.set(),threadLocal.get()其实都在对ThreadLocalMap进行读写,所以前面我才说ThreadLocal就像是一个用来操作ThreadLocalMap的工具类。
    在这里插入图片描述

ThreadLocal内存泄漏问题

这里要注意的一点是,ThreadLocalMap中entry的key,也就是ThreadLocal变量本身的引用是一个弱引用。
在这里插入图片描述
而弱引用只要垃圾回收机制一运行,不管JVM的内存空间是否充足,都会回收该对象占用的内存。因此ThreadLocalMap中的key很容易被回收了,key为null,而这时候整个ThreadLocalMap还在,因为ThreadLocalMap生命周期是和Thread一样的。key没了,value还在,这就造成了内存泄露
而解决这个问题的办法就是使用完ThreadLocal后,手动调用remove()方法释放内存空间。

  • 31
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值