Java常见面试题 -- ThreadLocal的原理、使用场景、内存泄露

原理

每一个Thread对象均含有一个ThreadMap类型的成员变量threadLoacls,它存储本线程中所有ThreadLocal对象及其对应的值。

ThreadLocalMap由一个个Entry对象构成

Entry 继承自 WeakReference <ThreadLoacl<?>>,一个 EntryThreadLoacl 对象和 object 构成。由此可见, Entry 的key是ThreadLocal对象,并且是一个弱引用。当没指向key的强引用后,该key就会被垃圾回收集器回收。

执行set方法时,ThreadLocal 首先会获取当前线程对象然后获取当前线程的ThreadLoaclMap对象 。再以当前ThreadLocal对象为key,将直接存储进ThreadLocalMap对象中。

get()方法执行 过程类似。ThreadLocal 首先会获取当前线程对象然后再获取当前线程的ThreadLocalMap对象,再以当前的ThreadLocal对象为key,获取对应的value。

由于每一条线程均含有各自私有的 ThreadLocalMap 容器,这些容器互相独立互不影响,因此不会存在线程安全性问题,从而无需使用同步机制来保证多条线程访问容器的互斥性。

使用场景:

  1. 在进行对象跨层传递的时候,使用ThreadLocal可以避免多次传递,打破层次间的约束
  2. 线程间数据隔离
  3. 进行事务操作,用于存储线程事务信息。
  4. 数据库链接,Session会话管理

Spring框架在事务开始时会给当线程绑定一个 Jdbc Connection,在整个事务过程中都是使用该线程绑定的 connection来执行数据库操作,实现了事务的隔离性,Spring框架里面就是用的ThreadLocal来实现这个隔离

内存泄露的原因,如何避免

内存泄露为程序在申请内存后,无法释放已申请的内存空间,一次内存泄露危害可以忽略,但内存泄露堆积后果很严重,无论多少内存,迟早会被占光。

不再会被使用的对象或者变量占用的内存不能被回收,就是内存泄露。

强引用: 使用最普遍的引用(new),个对象具有强引用,不会被垃圾回收器回收。当内存空间不足,Java虚拟机宁愿抛出OutOfMemoryError错误,使程序异常终止,也不回收这种对象。

如果想取消强引用和某个对象之间的关联,可以显示地将引用赋值为null,这样可以使JVM在合适的时间就会被回收该对象。

弱引用:JVM进行垃圾回收时,无论内存是否充足,都会被弱引用引用关联的对象,在Java中,用java.lang.ref.WeakReference类表示,可以在缓存中使用弱引用。

ThreadLocal的实现原理,每一个Thread维护一个ThreadLocalMap,key为使用弱引用的ThreadLocal实例,value为线程变量的副本

在这里插入图片描述
hreadLocalMap 使用 ThreadLoca l的 弱引用 作为key为null,如果一个ThreadLoca l不存在外部强引用时,key(ThreadLocal)势必会被GC回收,这样就会导致 ThreadLocalMap 中key为null,而value还存在着强引用,有thread线程退出以后,value的强引用链条才会断掉,但如果当前线程再迟迟不结束的话,这些key为null的Entry的value就会一直存在一条强引用链(红色链条)

key使用强引用

当hreadLocalMapd的key为 强引用回收ThreadLocal时,因为ThreadLocalMap还持有
ThreadLocal的强引用,如果没有手动删除,ThreadLocal不会被回收,导致Entry内存泄露

key使用弱引用

ThreadLocalMapkey为弱引用回收ThreadLocal时,由于ThreadLocalMap
持有ThreadLocal的弱引用即使没有手动删除。ThreadLocal也会被回收。当key为null,在下一次ThreadLocalMap调用set(),get(),remove()方法的时候会被清除value值。

因此,ThreadLocal内存泄露的根源是:由于ThreadLocalMap的生命周期跟Thread一样长,如果没有手动删除对应key就会导致内存泄露,而不是因为弱引用

ThreadLocal正常的使用方法:

  • 每次使用完ThreadLocal都调用它的remove()方法清除数据
  • 将ThreadLocal变量定义成private static,这样就一直存在ThreadLocal的强引用,也就能保证任何时候都能通过ThreadLocal的弱引用访问到Entry的value值,进而清除掉
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

眼里只有码

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值