Thread.currentThread.map当前线程的map
map的key是ThreadLocal的实例
当ThreadLocal被回收时,其key为null,但value可能泄露与内存所以采用弱引用
ThreadLocal的map的Entry为什么采用弱引用
防止内存泄漏,tl本身为null时,无法及时回收key为null的value
key 使用弱引用:引用的ThreadLocal的对象被回收了,由于ThreadLocalMap持有ThreadLocal的弱引用,即使没有手动删除,ThreadLocal也会被回收。value在下一次ThreadLocalMap调用set,get,remove的时候会被清除
ThreadLocal用途
声明式识事务
ThreadLocal原理
每个Thread 维护一个 ThreadLocalMap 映射表,这个映射表的 key 是 ThreadLocal实例本身,value 是真正需要存储的 Object
ThreadLocal 本身并不存储值,它只是作为一个 key 来让线程从 ThreadLocalMap 获取 value
ThreadLocalMap 是使用 ThreadLocal 的弱引用作为 Key 的,弱引用的对象在 GC 时会被回收
ThreadLocal导致内存泄露
ThreadLocalMap的生命周期跟Thread一样长
ThreadLocalMap使用ThreadLocal的弱引用作为key,
如果一个ThreadLocal没有外部强引用来引用它,那么系统 GC 的时候,
这个ThreadLocal势必会被回收,这样一来,ThreadLocalMap中就会出现key为null的
Entry,就没有办法访问这些key为null的Entry的value,如果当前线程再迟迟不结束的话(线程池重用线程),
这些key为null的Entry的value就会一直存在一条强引用链:
Thread Ref -> Thread -> ThreaLocalMap -> Entry -> value永远无法回收,
造成内存泄漏。
ThreadLocal的措施
get(),set(),remove()的时候都会清除线程ThreadLocalMap里所有key为null的value
但无法保证
static的ThreadLocal,延长了ThreadLocal的生命周期,可能导致的内存泄漏
分配使用了ThreadLocal又不再调用get(),set(),remove()方法,那么就会导致内存泄漏
ThreadLocal最佳实践
每次使用完ThreadLocal,都调用它的remove()方法,清除数据
在使用线程池的情况下,没有及时清理ThreadLocal,不仅是内存泄漏的问题,更严重的是可能导致业务逻辑出现问题。所以,使用ThreadLocal就跟加锁完要解锁一样,用完就清理
网友评论