TheadLocal

一:ThreadLocal的核心机制

1:每个Thread线程内部都有一个Map。

2:Map里面存储线程本地对象(key)和线程的变量副本(value)

 

Thread内部的Map是由ThreadLocal维护的,由ThreadLocal负责向map获取和设置线程的变量值。所以对于不同的线程,每次获取副本值时,别的线程并不能获取到当前线程的副本值,形成了副本的隔离,互不干扰

  • get()方法用于获取当前线程的副本变量值。
  • set()方法用于保存当前线程的副本变量值。
  • initialValue()为当前线程初始副本变量值。
  • remove()方法移除当前前程的副本变量值。

 

get()方法

1.获取当前线程的ThreadLocalMap对象threadLocals

2.从map中获取线程存储的K-V Entry节点。

3.从Entry节点获取存储的Value副本值返回。

4.map为空的话返回初始值null,即线程变量副本为null,在使用时需要注意判断NullPointerException。

 

set()方法

1.获取当前线程的成员变量map

2.map非空,则重新将ThreadLocal和新的value副本放入到map中。

3.map空,则对线程的成员变量ThreadLocalMap进行初始化创建,并将ThreadLocal和value副本放入map中

 

二:TheadLocal模式与同步机制的区别

1, 同步机制采用了“以时间换空间”的方式,提供一份变量,让不同的线程排队访问

而ThreadLocal采用了“以空间换时间”的方式,为每一个线程都提供一份变量的副本,从而实现同时访问而互不影响。

2,同步机制是为了同步多个线程对相同资源的并发访问,是为了多个线程之间进行通信的有效方式。

ThreadLocal是隔离多个线程的数据共享,从根本上就不在多个线程之间共享资源(变量),这样不需要对多个线程进行同步了。

3, 如果你需要进行多个线程之间进行通信,则使用同步机制。

如果需要隔离多个线程之间的共享冲突,可以使用ThreadLocal。

 

三:使用场景

1. 实现单个线程单例以及单个线程上下文信息存储,比如请求id,交易id等

2. 实现线程安全,非线程安全的对象使用ThreadLocal之后就会变得线程安全,因为每个线程都会有一个对应的实例

3. 存放一些线程用到的相关数据,避免在方法中来回传递参数

 

为什么ThreadLocalMap使用弱引用存储ThreadLocal?

那通常说的ThreadLocal内存泄漏是如何引起的呢?

我们注意到Entry对象中,虽然Key(ThreadLocal)是通过弱引用引入的,但是value即变量值本身是通过强引用引入。

这就导致,假如不作任何处理,由于ThreadLocalMap和线程的生命周期是一致的,当线程资源长期不释放,即使ThreadLocal本身由于弱引用机制已经回收掉了,但value还是驻留在线程的ThreadLocalMap的Entry中。即存在key为null,但value却有值的无效Entry。导致内存泄漏。

但实际上,ThreadLocal内部已经为我们做了一定的防止内存泄漏的工作

private int expungeStaleEntry(int staleSlot);

作用是擦除某个下标的Entry(置为null,可以回收),同时检测整个Entry[]表中对key为null的Entry一并擦除,重新调整索引。

该方法,在每次调用ThreadLocal的get、set、remove方法时都会执行,即ThreadLocal内部已经帮我们做了对key为null的Entry的清理工作。

但是该工作是有触发条件的,需要调用相应方法,假如我们使用完之后不做任何处理是不会触发的

(强制)在代码逻辑中使用完ThreadLocal,都要调用remove方法,及时清理,同时对异常情况也要在finally中清理。

ThreadLocal一般加static修饰

 

假如使用强引用,当ThreadLocal不再使用需要回收时,发现某个线程中ThreadLocalMap存在该ThreadLocal的强引用,无法回收,造成内存泄漏。

因此,使用弱引用可以防止长期存在的线程(通常使用了线程池)导致ThreadLocal无法回收造成内存泄漏。

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值