ThreadLocal
每个线程都有独立的副本,线程之间互不影响
- 每个线程都有一个threadLocals属性,这是一个ThreadLocalMap,底层结构类似HashMap,Entry的key为ThreadLocal的弱引用,当发生hash碰撞时采用开放定址法以当前位置未基准找到下一个位置,直到为空
一、java引用的分类
- 强引用:垃圾回收器不会回收被强引用引用的对象
- 软引用:当内存不足时,会对软引用的对象进行GC回收,一般用于缓存技术
- 弱引用:发生GC时会回收弱引用引用的对象
- 虚引用:如果一个对象仅仅被虚引用引用,那么他相当于没有任何引用,一般用于垃圾回收状态的跟踪
二、ThreadLocalMap的Entry的key为什么使用弱引用?
- 一般通过外部强引用ThreadLocal操作,外部强引用置为null后,内部强引用也没有意义
- 弱引用可以避免内存泄露,等待下次get\set\remove时会将key为null的删除
三、建议把ThreadLocal修饰为static,为什么?
ThreadLocal实现线程隔离在于ThreadLocalMap,而不是它本身,ThreadLocal只作为key使用,初始化一次就够了,不需要多次初始化
四、ThreadLocal存在的问题以及如何解决
- 问题:ThreadLocal存在内存泄露问题,ThreadLocalMap中Entry的key使用ThreadLocal的弱引用,所以当外部没有强引用引用ThreadLocal时,线程一直执行或者线程复时,而GC又将该弱引用回收,那么就会存在Key为null的value值,而我们又无法获取该值,导致内存泄露。
- 解决:操作完ThreadLocal后执行remove方法,会清除key为null的Entry(调用get,set方法时也会清空)