ThreadLocal

前置知识
Java中有些引用类型?
Java中主要有4种引用类型,分别是:强、软、弱、虚。他们主要跟Java的垃圾回收机制有关
强引用:Java中默认的引用类型,一个对象如果具有强引用,那么只要这种引用还存在就不会被回收
软引用:在内存充足时,是不会GC这个对象的。只有在JVM内存不足的时候才会调用垃圾回收器回收掉这个对象
弱引用:弱引用所引用的对象只能生存到下次GC之前,当发生GC的时候,无论当前内存是否足够,弱引用所引用的对象都会被回收掉。它是和强引用一起配合使用,用来解决内存泄漏问题,比如我们今天所聊的ThreadLocalMap中的Entry对象,就使用了弱引用
虚引用:虚引用是所有引用中最弱的一种引用,其存在就是为了将关联虚引用的对象在被GC掉之后收到一个通知

基础理解
ThreadLocal是Java所提供的线程本地存储机制,是用来解决Java多线程并发问题的一种途径,通过为每一个线程创建一分共享变量的副本,来保证各个线程之间的变量的访问和修改互不影响

内部原理
Thread类中维护了ThreadLocalMap成员变量
而ThradLocalMap维护了以ThreadLocal为key需要存储数据为value的Entry数组

Entry实际上继承了一个ThreadLocal类型的弱引用,并在其作为key,value为Object类型

内存泄漏问题

ThreadLocal对象是有两个引用的
一个是栈上的ThreadLocal引用
一个是ThreadLocalMap的Entry对象的key对他的引用
假如栈上的ThreadLocal引用已经不再使用了,因为用了弱引用,那么ThreadLocal对象在下次GC时,就会被垃圾回收掉,这样做可以很大程度的避免因为使用ThreadLocal的使用而导致的OOM问题,但是这个问题却无法彻底避免,虽然key是弱引用,但是value却是强引用,而且它的生命周期是和Thread一样的,也就是说只要Thread还在,这个对象就无法被回收,Thread对象长期存在的典型案例就是线程池,在线程池中重复利用线程的时候,就会导致这个引用一直在,导致value一直无法被回收

解决方案
当我们每一个ThreadLocal用完之后,手动调用remove()方法,就可以在下次GC的时候,把Entry清理掉

使用场景
1.使用日期工具类,当用到SimpleDateFormat作为成员变量时,可以使用ThreadLocal保证线程安全
2.全局存储用户信息
3.保证一个线程获取到的数据库连接Connection是同一个
4.Spring框架中也大量使用了ThreadLocal保证线程安全

posted @   狗狗没有坏心眼  阅读(8)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 零经验选手,Compose 一天开发一款小游戏!
· 通过 API 将Deepseek响应流式内容输出到前端
· AI Agent开发,如何调用三方的API Function,是通过提示词来发起调用的吗
点击右上角即可分享
微信分享提示