ThreadLocal源码解读

经过查询网上资料和看源码解读总结:
1. ThreadLocal 使用内部类ThreadLocalMap存储数据,而ThreadLocalMap的引用(使用或定义)却在Thread类内,所以ThreadLocal 是单独线程使用,不能解决共享对象的多线程访问的竞争问题。
这里写图片描述
2. ThreadLocalMap内部的Entry(存储数据)使用弱引用, 引用ThreadLocal 作为Entry的key值,而当ThreadLocal没有强引用时会被gc回收,ThreadLocalMap得key就会出现null值,这些key为null的value就不能被访问到,而当前线程Thread一直不结束的话,Entry的值value 就会一直有个强引用(Object),gc就永远无法回收,造成内存泄漏。
而为了避免上述情况,ThreadLocalMap在getEntry(ThreadLocal key)方法和set(ThreadLocal key, Object value)内进行了解决:getEntry首先会通过直接索引位置(通过ThreadLocal.threadLocalHashCode & (table.length-1)运算得到 )获取Entry e,如果e不为null并且key相同则返回e,否则会向下一个位置查询,如果查询过程中,key值为空,则设置key对应value为null,这样就不会有强引用,会被gc回收,最终会返回一个e不为空,并且key相等的Entry。
 但是光这样还是不够的,上面的设计思路依赖一个前提条件:要调用ThreadLocalMap的getEntry函数或者set函数。这当然是不可能任何情况都成立的,所以很多情况下需要使用者手动调用ThreadLocal的remove函数,手动删除不再需要的ThreadLocal,防止内存泄露。所以JDK建议将ThreadLocal变量定义成private static的,这样的话ThreadLocal的生命周期就更长,由于一直存在ThreadLocal的强引用,所以ThreadLocal也就不会被回收,也就能保证任何时候都能根据ThreadLocal的弱引用访问到Entry的value值,然后remove它,防止内存泄露。

注:

ThreadLocal.threadLocalHashCode & (table.length-1) 为 int & int 运算 (二进制运算)
按位与运算符“&”,如果两个运算数都是1,则结果为1。其他情况下,结果均为零。
private final int threadLocalHashCode = nextHashCode();
private Entry[] table;

强引用(Strong Reference):通常我们通过new来创建一个新对象时返回的引用就是一个强引用,若一个对象通过一系列强引用可到达,它就是强可达的(strongly reachable),那么它就不被回收
软引用(Soft Reference):软引用和弱引用的区别在于,若一个对象是弱引用可达,无论当前内存是否充足它都会被回收,而软引用可达的对象在内存不充足时才会被回收,因此软引用要比弱引用“强”一些
虚引用(Phantom Reference):虚引用是Java中最弱的引用,那么它弱到什么程度呢?它是如此脆弱以至于我们通过虚引用甚至无法获取到被引用的对象,虚引用存在的唯一作用就是当它指向的对象被回收后,虚引用本身会被加入到引用队列中,用作记录它指向的对象已被销毁。

资料:https://www.cnblogs.com/xzwblog/p/7227509.html
http://blog.csdn.net/u014326264/article/details/50235963
https://www.cnblogs.com/absfree/p/5555687.html#undefined

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值