ThreadLocal原理及内存泄漏原因

文章详细介绍了Java中的ThreadLocal机制,包括其作为线程局部变量的作用,确保线程安全的数据绑定。ThreadLocal的set和get方法的底层原理涉及到强引用和弱引用。弱引用用于key以防止内存泄露,而强引用用于value确保值在需要时可访问。文章还讨论了不正确使用ThreadLocal可能导致的内存泄露问题,并给出了业务场景中如全局存储用户信息的例子。
摘要由CSDN通过智能技术生成

        在了解ThradLocal原理前,是有必要需要了解一下java的引用类型的,因为Threadlocal的底层使用了弱引用,可以顺便把这方面的知识过一下,再加上面试的时候,这个也是比较常问的        

1.java引用类型:

        引用类型分别有强,软,弱,虚类型

2.分别说一下这些引用类型的特点

         强引用:在java里面直接new出来的对象属于一个强引用,如果一个对象具有强引用,JVM就不会去进行回收它,当内存空间不够的时候就会报OOM错误

        

        软引用:如果一个对象只具备软引用,那么当内存空间不够的时候,JVM就会把这个对象进行回收(Soft Reference
       

        弱引用:如果一个对象只具备了弱引用,那么被jvm的gc线程检测到了,这个对象就会被回收(Weak Reference)
        

        虚引用:是直接管理本地内存的

3.ThradLocaL

        ThreadLocL是线程的一个局部变量,这种变量可以在多线程的情况下,让数据与当前线程进行绑定,这个数据其他线程是不能进行读取跟修改的,从而确保了线程的安全。

4.set方法的底层原理

             在ThreadLocL调用set方法的时候,set方法底层是先获取到当前线程,然后再通过getmap方法,来获取当前线程的ThreadLocLs变量,然后再把ThradLocL作为key,set方法传进参数作为value,通过ThreadLocLs的set方法保存起来,在保存的时候,key会以弱引用的形式保存起来,value是以强引用的形式进行保存

        所以当Threadlocl调用set方法来保存值的时候,并不是保存的在Threadlocl里面,而是保存在了当前线程的ThreadLocLs变量中(这个变量的类型是ThreadLocalMap),而这个变量是一个map结构,里面的key保存了调用set方法的ThreadLocL引用,value是需要保存的值

5.get方法的底层原理

        ThreadLocL调用get方法,首先会获取当前线程,然后再通过getmap方法,来获取当前线程的ThreadLocLs变量,通过变量的getEntry方法,参数是ThreadLocL,就可以来获取到所保存的数据

6.为什么key要设置为弱引用,强引用不行吗?

       用强引用的话有可能会造成内存泄露,当线程不再需要使用某个Threadlocl的时候,因为key是弱引用,所以只要被jvm的gc线程检测到就会被回收,如果key是强引用类型,那么这个key就没有办法被回收,如果有很多线程的Threadlocl一直没有被使用,然后又没有被回收,那么时间长了就有可能爆oom错误

7.为什么value要设置为强引用,弱引用不行吗?

        如果value是弱引用,只要jvm执行一次gc操作,那么这个value就被回收掉了,取值的时候会返回null,所以只能是强引用

8.内存泄露

        第一种情况:如果key被jvm的gc回收掉了,那么value值就无法被访问,如果线程一直在运行,那么就会有可能造成oom错误,虽然调ThreadLocL的set,get方法的时候会把key为null的Entry对象删除掉,但如果这个线程很久都没有进行这两个方法的调用,那也是无法进行回收,所以我们在使用完成之后要手动remove来保证代码的安全性
 

        第二种情况:如果使用了线程池进行线程复用,线程使用完成之后,如果不进行remove操作的话,那么线程的ThreadloclMap保存的值会越来越多,还可能出现value的值被覆盖的情况,所以也需要手动remove操作来保证代码的安全性

9.ThreadLocalMap.Entry中的key为什么不会被错误清理?

         一个对象在只有弱引用指向它时,一旦jvm执行gc操作,那它就会被回收,但是ThreadLocal对象除了在Entry中有弱引用指向,在业务代码中还有强引用指向,所以不会被错误清理

10.ThreadLocal在业务场景中的使用

        全局存储用户信息,在我负责的项目里面,是有过滤器的,在过滤器中对token进行验证,验证成功之后,就把对应的token以及该用户比较常用的数据保存到ThreadLocal,然后需要就可以直接使用,但是在使用之后,需要及时把ThreadLocl里面的数据给清理,否则容易内存泄漏

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值