ThreadLocal的结构
每个线程对象都有一个ThreadLocal.ThreadMap维护了一个ThreadMap;ThreadMap维护了Entry结构的一个数组对象。
static class Entry extends WeakReference<ThreadLocal<?>> {
/** The value associated with this ThreadLocal. */
Object value;
Entry(ThreadLocal<?> k, Object v) {
super(k);
value = v;
}
}
ThreadLocal为什么会出现内存溢出的问题
ThreadLocal的key是一个软引用对象。
-
软引用对象是当发生gc的时候,软引用对象,如果在gc的时候并且没有被引用了,就会被进行回收。如果当前线程ThreadLocal没有被引用了,当gc的时候,就会被回收掉key,但是当前线程还存在着对value的强引用一直无法被回收掉,所以就造成了oom
-
Current Thread Reference --> Current Thread --> ThreadLocalMap --> EntryValue --> Object
ThreadLocal为什么要将key设置为弱引用有什么好处
设置为弱引用,gc回收的时候会被回收掉,但是key为null,value不为null的对象没办法被回收掉。所以在ThreadLocal的时候的set,get,remove的时候会回收掉key为value的对象。
-
如果设置为强引用的话,使用这些方法是没办法进行回收掉的。 分配了ThreadLocal对象,但是并没有执行其get、set、remove方法,导致不能有效的清除null对象;
-
使用线程池的情况下,使用完ThreadLocal一定要使用remove方法即时清理,因为ThreadLocal是属于某个线程的,而在使用线程池的情况下,这些线程都是可重复利用、存活时间长的线程,如果在使用过程中不仅从即使的remove,那么不仅会造成内存泄露的问题,还会引发一些功能逻辑问题,比如,B请求可能和A请求分配到了线程池中的同一个线程,那么它们拿到的ThreadLocal就是一样的。
为什么value也不设置为弱引用