
与其他map相类似,ThreadLocalMap内部存储的数个格式也是
通过阅读源码,不难发现。ThreaLocalMap在使用的时候。其实都是在方法内部,获取到了本地线程,进行操作的。
ThreadLocalMap整体的数据结构可以理解为一个只能存放单个key对象的map集合。
ThreadLocal的使用场景,其实比较容易。首先得知道ThreadLocal得特性才行。
特性比如:
首先内存泄漏是什么东西呢?
内存泄漏是程序在申请内存后,无法释放已申请的内存空间,多次内存泄漏就会导致内存耗光的严重问题。
在这里就有个概念了,在Java中存在多种应用对象。
强引用:使用最普遍的引用(new),一个对象具有强引用,不会被垃圾回收器回收。当内存空间不足,java虚拟机宁愿抛出OutOfMemoryError错误,使程序异常终止,也不回收这种对象。
如果想取消强引用和某个对象之间的关联,可以显式地将引用赋值为null,这样可以使JVM在合适的时间回收该对象。
弱引用:JVM进行垃圾回收时,无论内存是否充足,都会回收被弱引用关联的对象。在java中,用java.lang.ref.WeakReference类来表示。可以在缓存中使用弱引用。
我们的ThreadLocal存放得entry就是被WeakReference标记得弱引用类型对象。
ThreadLocalMap使用ThreadLocal的弱引用作为key,如果一个ThreadLocal不存在外部强引用时,key(ThreadLocal)就会被GC回收,这样就会导致ThreadLocalMap中key为null,而value还存在强引用,只用thread线程退出,value的强引用链条才会断掉,但如果当前线程未结束,这些key为null的Entry的value就会一直存。
如果ThreadLocalMap的key为强引用回收ThreadLocal时,因为ThreadLocalMap还持有ThreadLocal的强引用,如果没有手动删除,ThreadLocal就不会被回收,导致Entry内存泄漏。
ThreadLocalMap的key为弱引用回收ThreadLocal时,由于ThreadLocalMap持有ThreadLocal的弱引用,即使没有手动删除,ThreadLocal也会被回收。当key为null,在下一次ThreadLocalMap调用set(),get(),remove()时会清除value的值。
因此,ThreadLocal内存泄漏的根源是由于ThreadLocalMap的生命周期和Thread一样长,如果没有手动删除对应key就会导致内存泄漏,而不因为弱引用。
如何避免ThreadLocal产生的内存泄漏ThreadLocal正确的使用方法: