ThreadLocal的一些理解。

在聊ThreadLocal之前,首先咱们得先聊一下,强引用,软引用,弱引用与虚引用的问题。


1.强引用

Object  o = new Object();这里的o就是强引用,如果引用一直存在,该对象就不会被回收。

2.软引用

       A a = new A();    

       SoftReference<A> soft = new SoftReference<A>(a);

如果通过-Xmx设置最大的堆为3M,上面的soft对象占用2M,后面你再new一个大小为2M的对象,你会发现这个soft对象会自动被回收掉。这就是软引用,当堆内存不够分配空间的时候,会被自动回收。

应用场景是:缓存

3.弱引用

    B b = new B();

    WeakReference<B> weak = new WeakReference<B>(b);

直接说结论吧,弱引用 只要jvm发生垃圾回收,就会被回收。那么应用场景是什么呢?这就和我们今天讲的ThreadLocal有关系了,主要是防止一些特定情况下发生内存泄露而使用的。具体什么特定情况,下面再说。

4.虚引用

   C c = new C(); 

   Queue queue = new Queue();

   PhantomReference<C> phantom = PhantomReference<C>(c,queue);

   phantom.get();

你会发现phantom.get()得到的值是null,这就是虚引用,那么可能就会有疑问,一new出来就为null,有什么意义呢?其实你发现后面还有一个队列,这个队列就表示将这个虚引用放入到该队列之中,然后起到一个标志性的作用,告诉计算机这里有一个直接内存需要被回收。

例如上图,jvm中的一个引用直接指向堆外内存的区域,那么如果按照正常的java对象回收,jvm只会回收jvm中堆的对象,那么咱们要想回收堆外的对象,就得告诉jvm让jvm告诉计算机去回收,说白了,这是一种特殊情况,所以需要一个标志,虚引用就是起到该作用。


强,软,弱,虚引用都讲完了,现在再来看ThreadLocal

    D d = new D();

    ThreadLocal<D>  tl = new ThreadLocal<D>();

    tl.set(d);

以上最后一行代码发生了什么很关键:

set方法不难发现,先取当前线程的TheadLocalMap,然后把this也就是当前的tl对象作为key,然后d为value值。再往下看set方法:

是new了一个Entry对象,并且通过构造函数,存进entry里面了。那么这个Entry又是什么呢?继续往下看:

这里会发现两个问题,上面说的存进ThreadLocalMap并不是Map的子类,而是一个对象,然后通过该对象里面的Entry对象来存储key和value,而且这里Entry又继承了一个弱引用对象,并且在构造函数中将key值传了进去,再说明白一点,这个key最后就变成了一个弱引用对象了,在jvm发生垃圾回收的时候就会被回收。

那么为什么要这样呢?


假如我们的key是强引用,那么如果tl=null的时候这个key也不会被回收,应该thread还存在那么Entry也存在,这样就有内存泄露的风险,因为有的线程是全天24小时在跑的,而这里如果是弱引用,那么在垃圾回收的时候就会自动被清除掉。

那么还有一个问题,虽然这个key是被回收了,但是这个value值还是个强引用,如果线程不死,那么也将一直存在,并且它的key是null,故还是会引起内存泄露问题,这也就是我们常说的ThreadLocal内存泄露。

如何解决?显示的调用remove方法就可以,其实在set和get方法的时候ThreadLocal都会自动清掉key为null值的entry。


 最后说一下ThreadLocal的使用场景,举一个例子如果A方法调用B方法,B方法又调用C方法,如果有一个特定的参数,需要从A传到C,最常用的就是加形参,但是有个ThreadLocal我们就可以把这个参数存进去,然后在C中使用即可。如spring的事务@Transactional中开启事务的connection对象就是存在ThreadLocal中。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值