ThreadLocal详解。以及对应会出现的问题

1.什么是ThreadLocal? 如何实现的

        ThreadLocal为java下的一个类,主要用于解决线程间数据隔离的问题。简单来说,它为每个线程提供了一个独立的变量副本,使得每个线程在访问该变量时,实际上获取到的是自己线程独有的副本,而不是其他线程可见的共享变量。这样就避免了线程间的竞态条件和数据同步问题,尤其适用于那些需要在线程内保持状态,但又不希望这个状态被其他线程干扰或者影响的情况。

总结来说 就是可以用来解决多线程程序中并发问题, 每个线程共享一个变量来保证各个线程之间的变量访问与修改, 其中线程之间互相不影响。

ThreadLocal为每个使用它的线程提供了一个独立的变量副本。每个线程都通过其自身的ThreadLocalMap(一个定制化的哈希表)来存储这些副本。当一个线程第一次读取某个ThreadLocal变量时,如果当前线程的ThreadLocalMap中尚不存在对应的键值对,就会创建该变量的副本,并将其放入ThreadLocalMap中。后续对该变量的所有操作(如读取、更新等)都将针对这个副本进行,与其他线程完全隔离。

        我们关注ThreadLocal只需要关注一个内部的map. 也是基于K-V结构 key就是当前的ThreadLocal对象,而v就是保存想要保存的值(比如token  用户信息等) , 无需用其他的代码访问

2.出现的问题

        1.ThreadLocal在中会出现内存泄露, 这是一个比较典型的问题

       会导致ThreadLocal内存泄漏的部分其实就是他在堆上存储的ThreadLocalMap中的K-V部分

image.png



ThreadLocalMap的key就是ThreadLocal对象,他有两个引用源,一个是栈上的ThreadLocal引用,一个是ThreadLocalMap中的Key对他的引用。

image.png



而对于value来说,他的引用就一条,就是从Thread对象过来的。
 

image.png



所以,就会出现以下两种情况:

1、栈上的ThreadLocal Ref引用不在使用了,即方法结束后这个对象引用就不再用了,那么,ThreadLocal对象因为还有一条引用链在,所以就会导致他无法被回收,久而久之可能就会对导致OOM。

image.png



2、Thread对象如果一直在被使用,比如在线程池中被重复使用,那么从这条引用链就一直在,那么就会导致ThreadLocalMap无法被回收。
 

image.png



弱引用解决内存泄漏

我们先来说说JDK自己帮我们实现的一部分功能,主要是解决上面说的第一种情况:

栈上的ThreadLocal Ref引用不在使用了,即方法结束后这个对象引用就不再用了,那么,ThreadLocal对象因为还有一条引用链在,所以就会导致他无法被回收,久而久之可能就会对导致OOM。

为了解决这个问题,ThreadLocalMap使用了弱引用。
 

image.png

因为我们可以看到,虽然key是弱引用,但是value的那条引用,还是个强引用呢!而且他的生命周期是和Thread一样的,也就是说,只要这个Thread还在, 这个对象就无法被回收。

那么,什么情况下,Thread会一直在呢?那就是线程池。

在线程池中,重复利用线程的时候,就会导致这个引用一直在,而value就一直无法被回收。

那么如何解决呢?

ThreadLocalMap底层使用数组来保存元素,使用“线性探测法”来解决hash冲突的,在每次调用ThreadLocal的get、set、remove等方法的时候,内部会实际调用ThreadLocalMap的get、set、remove等操作。

而ThreadLocalMap的每次get、set、remove,都会清理key为null,但是value还存在的Entry。

所以,当我们在一个ThreadLocal用完之后,手动调用一下remove,就可以在下一次GC的时候,把Entry清理掉。

  • 30
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值