【Java基础知识】ThreadLocal

一 Java中的引用关系

Java中的引用分为了强引用、弱引用、软引用、虚引用
强引用: 垃圾回收的时候,如果内存不足也不会进行垃圾回收,会报out-of-memory异常
弱引用: 垃圾回收的时候,如果内存不够,则数据被回收.
软引用: 垃圾回收的时候,软引用会立刻进行回收
虚引用: 垃圾回收的时候,软引用会立刻进行回收

二 ThreadLocal代码实现

ThreadLocal是线程本地变量,存储在ThreadLocal里面的数据都是
线程安全的.

一般ThreadLocal适用的场景多是各个线程间没有变量共享需要的同步问题场景,比如一个简单的SimpleDateFormat类,该类不是线程安全的,却是有状态的,如果将SimpleDateFormat设置为静态的,所有线程共享,那么就会出现线程安全的问题,其中一个线程修改日期格式为“yyyyMMdd”,然后可能会影响到另外一个需要格式为“yyyy-MM-dd”的线程。但是如果在方法中每次用到的时候都new一个SimpleDateFormat类又太费内存(SimpleDateFormat这种简单的类倒还好,若是一些比较占用资源的比如数据库连接类等,就会让加大整个数据库的压力),这时候采用ThreadLocal为每一个线程保存一份SimpleDateFormat副本,这样既不会说每次调用方法都会生成一个对象,也不会在并发时产生线程同步问题。这就像是在共享一个静态变量和每次使用都new一个对象两者之间的一种折中处理方法。

2 自己实现的ThreadLocal

在这里插入图片描述
通过一个全局map, key是Thread对象,value是对应存储的数据,这种情况下
如果map不销毁,对应的Thread线程就不发被回收,导致内存泄露

3 JDK中使用的ThreadLocal

在这里插入图片描述
JDK8中在Thread对象中引用ThreadLocalMap,ThreadLocalMap的生命周期是Thread是同一个生命周期.

4 ThreadLocalMap的实现

(1) Entry数组实现
在这里插入图片描述
Entry数组是线程中实际存放数据的地方,key是ThreadLocal,是一个弱引用,value是对应存储的值.
为什么ThreadLocalMap#key是一个弱引用

如果外部不使用了ThreadLocal,则对应的数据不应该存储在ThreadLocal中,应该被删除掉,防止内存泄漏

ThreadLocalMap的属性

        private static final int INITIAL_CAPACITY = 16;
    	//存储数据的地方
        private Entry[] table; //
    	//数量
        private int size = 0;
        private int threshold; // Default to 0

5 ThreadLocal的方法

ThreadLocal#set()方法

在这里插数据入图片描述
(1) 第一步 获取到当前线程的ThreadLocalMap
(2) 第二步 初始化ThreadLocalMap
(3) 第三步 将ThreadLocal作为key,value值作为值,设置到map中

ThreadLocal # get()方法

在这里插入图片描述
方法主要完成两个功能:
(1) 完成数据的读取
(2) 将ThreadLocalMap中key为NULL的数据从ThreadLocalMap中删除

ThreadLocalMap中的entry其实是继承的弱引用,如果该弱引用指向的ThreadLocal没有在外部被强引用指向的话,在下次gc的时候就会被回收,那这样的话就会出现ThreadLocalMap中存在key为null的情况,这样的数据对于map来讲是脏数据,这样的脏数据没有用,却一直占用着map的存储空间,这其实就是一种内存泄漏,所以需要来释放掉这些空间

三 ThreadLocalMap的内存泄漏问题

如果ThreadLocal无强引用进行应用,则在垃圾回收的时候会把这个key进行回收.
这个时候,因为线程还存活,所以ThreadLocalMap依旧存在,但是key为null,这个
key对应的value就无法被访问到了,造成内存泄漏.
JDK团队自己的解决办法
调用get()、set()方法的时候,自动清理掉ThreadLocalMap中key为null的数据
开发者的解决办法
使用ThreadLocal后,调用ThreadLocal

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值