1.java多线程之ThreadLocal

1.ThreadLoacal是什么?

该类提供了线程局部 (thread-local) 变量。这些变量不同于它们的普通对应物,因为访问某个变量(通过其 get 或 set 方法)的每个线程都有自己的局部变量,它独立于变量的初始化副本。 ThreadLocal实例通常是类中的 private static 字段,它们希望将状态与某一个线程(例如,用户 ID 或事务 ID)相关联。

所以ThreadLocal与线程同步机制不同,线程同步机制是多个线程共享同一个变量,而ThreadLocal是为每一个线程创建一个单独的变量副本,故而每个线程都可以独立地改变自己所拥有的变量副本,而不会影响其他线程所对应的副本。可以说ThreadLocal为多线程环境下变量问题提供了另外一种解决思路。

ThreadLocal定义了四个方法:

get():返回此线程局部变量的当前线程副本中的值。

initialValue():返回此线程局部变量的当前线程的“初始值”。

remove():移除此线程局部变量当前线程的值。

set(T value):将此线程局部变量的当前线程副本中的值设置为指定值。

除了这四个方法,ThreadLocal内部还有一个静态内部类ThreadLocalMap,该内部类才是实现线程隔离机制的关键,get()、set()、remove()都是基于该内部类操作。ThreadLocalMap提供了一种用键值对方式存储每一个线程的变量副本的方法,key为当前ThreadLocal对象,value则是对应线程的变量副本。

对于ThreadLocal需要注意的有两点:

ThreadLocal实例本身是不存储值,它只是提供了一个在当前线程中找到副本值得key。

是ThreadLocal包含在Thread中,而不是Thread包含在ThreadLocal中,有些小伙伴会弄错他们的关系。

2.ThreadLocalMap是什么?

ThreadLocalMap是ThreadLocal内部还有一个静态内部类,ThreadLocalMap其内部利用Entry来实现key-value的存储。Entry的key就是ThreadLocal,而value就是值。同时,Entry也继承WeakReference,所以说Entry所对应key(ThreadLocal实例)的引用为一个弱引用。

ThreadLocalMap定义了两个方法:

getEntry(ThreadLocal<?> key):获取currentThread对应的value

set(ThreadLocal key, Object value) :除了存储元素外,还有一个很重要的作用,就是replaceStaleEntry()和cleanSomeSlots(),这两个方法可以清除掉key == null 的实例,防止内存泄漏。

3.ThreadLocal为什么会内存泄漏?

每个Thread都有一个ThreadLocal.ThreadLocalMap的map,该map的key为ThreadLocal实例,它为一个弱引用,我们知道弱引用有利于GC回收。当ThreadLocal的key == null时,GC就会回收这部分空间,但是value却不一定能够被回收,因为他还与CurrentThread存在一个强引用关系。由于存在这个强引用关系,会导致value无法回收。如果这个线程对象不会销毁那么这个强引用关系则会一直存在,就会出现内存泄漏情况。所以说只要这个线程对象能够及时被GC回收,就不会出现内存泄漏。

那么怎么避免这个问题:

如果遇到key == null的情况,我们也可以显示调用ThreadLocal的remove()方法进行处理。

总结

  • ThreadLocal 不是用于解决共享变量的问题的,也不是为了协调线程同步而存在,而是为了方便每个线程处理自己的状态而引入的一个机制。这点至关重要。

  • 每个Thread内部都有一个ThreadLocal.ThreadLocalMap类型的成员变量,该成员变量用来存储实际的ThreadLocal变量副本。

  • ThreadLocal并不是为线程保存对象的副本,它仅仅只起到一个索引的作用。它的主要木得视为每一个线程隔离一个类的实例,这个实例的作用范围仅限于线程内部。

附上一张关系图(图片来自http://www.jianshu.com/p/ee8c9dccc953):

转载来源:

https://mp.weixin.qq.com/s?__biz=MzAxODcyNjEzNQ==&mid=2247485208&idx=1&sn=b025858938274d40346c851d2ddab2ce&chksm=9bd0aa80aca7239625634023b09564409ba85c205cabfcc143d121291f6f88e6a68ba130de8a&scene=21#wechat_redirect

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值