Threadlocal&&JAVA的四大引用

threadlocal是什么?

做线程变量隔离的

什么场景下会用到thread local?

当一个用户请求,我们的后端接口需要用到这个用户信息,整个链路下来,都要把这个用户信息当参数传递下来,会非常的麻烦,这时候就想到有没有一个地方,可以专门存储用户信息的,用的时候直接get一下就拿到了,那当然有了,这个东西就叫做threadlocal

threadlocal的实现方式

每一个线程都有一个自己的map,也就是threadlocalmap,以下面代码为例

key:threadlocal实例(userInfoThreadLocal)

value:存进去的数据(user Information)

为什么要key要设置生实例,直接一个大的map不好吗?

jdk1.4之前确实是这么设计的,但是他有两个缺点

1.隔离性不满足(因为所以的线程都放在一张大的map中,我不保证有其他线程把我的数据修改掉)

2.效率低,空间利用率也低(要知道,可能一个请求要好几百的线程的,要是设计成map的话第一层的key是线程id,value又是一个map,key是业务key,value才是我真正要的值,这样的化我还要现根据我的线程id找到对应的map,然后再根据map找到我要的用户信息?这样太麻烦了!)

jdk1.4之后,才演变到现在这个形势,key是直接存储的是threadlocal实例

threadlocal带来的问题

1.key的内存泄露问题

当我们new出来一个threadlocal时,会在堆中创建出一个实例对象,然后栈中的userlocal的引用指向堆中的对象,因为每一个线程都会有自己的一个map,当代码中使用threadlocal中的map去set添加数据的时候,线程中的map也会指向队中的对象,当代码执行完之后,栈中的引用没了,正常来说堆中的对象是需要被回收的,但是因为和线程中的map是强引用的关系,所以不能被回收掉,造成key的内存泄漏,所以会把key设置成弱引用,一般不被使用,就会gc回收掉

2.value的内存泄漏问题

上面说的问题能解决key的内存泄漏问题,那value怎么办呢?有的同学会想,那value和key也是一样的,也设置成弱引用,这么想就大错特错,value必须设置成强引用,为什么?

因为如果value也设置成弱引用,那他随时会gc删除掉,那我其他方法还是要用这个value的话,我getkey,value就变成null了,(比如我刚塞入的用户信息,是弱引用的关系,value被回收掉了,下次再次get的时候,数据没了!!哭死)所以value要设置成强引用,不能被回收掉。

但是当key不再被使用,被回收掉了,value因为是强引用,不会被回收掉,会出现value的内存泄露问题

那value什么时候被回收呢?

key变成null的时候,value就会被回收掉。拿什么时候会清除成null呢?当一个线程快要结束的时候,要手动进行清除remove一下才行,不然下一个线程进来,因为大家用的都是同一个key,由于value没有被清除掉,会用到上一个线程重复的数据

四种引用类型

1.强引用

强引用是一定不会被回收的对象,当内存不足的时候,jvm会报OOM

Object object = new Object()//这个就是强引用

在treadlocal中 value就是强引用,因为不需要被垃圾回收掉,在一个线程生命周期内,都需要用到这个value值

那强引用的对象他什么时候会被回收?

当new了一个对象,具体的对象会再堆中,方法里面的引用会存在再栈中,栈的引用指向堆中的对象,当一个方法结束了,栈中的引用也会随之消失,那这时候堆中的对象就会被回收掉

但是如果这个对象是全局变量,栈中的引用会一直存在,那这个时候就要手动弱化引用,帮助gc回收掉,因为强引用是什么时候都不会被gc回收掉的

object=null

这个时候,gc认为这个对象不存在引用,这时候就会被回收掉

这个代码可以参考一下ArrayList的clear源码,他就是手动将全局变量设置成了null,帮助gc回收,及时释放掉内存

2.软引用

当内存不足的时候,才会进行gc垃圾回收

例子:当浏览器按回退的按钮时,如果内存还充足,对象就不会被回收掉

3.弱引用

一旦发现这个对象是弱引用,不管内存充足与否,都会被gc垃圾回收掉

在threadlocal中,key就是弱引用(具体为什么参考上面笔记)

4.虚引用

并不会取决于对象的生命周期,如果这个对象只是虚引用,那会认为,这和没有引用没有啥区别,在任何时候都有可能被回收掉

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值