ThreadLocal原理
Thread类中有ThreadLocalMap。ThreadLocalMap是HashMap的ThreadLocal定制版。 ThreadLocal中存的东西实际上是存在当前Thread中的ThreadLocalMap中。存东西的过程: 1)拿当前Thread 2)拿当前Thread的ThreadLocalMap(懒加载) 3)操作ThreadLocalMap
public class Thread implements Runnable {
//......
//与此线程有关的ThreadLocal值。由ThreadLocal类维护
ThreadLocal.ThreadLocalMap threadLocals = null;
//与此线程有关的InheritableThreadLocal值。由InheritableThreadLocal类维护
ThreadLocal.ThreadLocalMap inheritableThreadLocals = null;
//......
}
ThreadLocal类的set()方法
public void set(T value) {
//获取当前请求的线程
Thread t = Thread.currentThread();
//取出 Thread 类内部的 threadLocals 变量(哈希表结构)
ThreadLocalMap map = getMap(t);
if (map != null)
// 将需要存储的值放入到这个哈希表中
map.set(this, value);
else
createMap(t, value);
}
ThreadLocalMap getMap(Thread t) {
return t.threadLocals;
}
内存泄漏问题
ThreadLocalMap的key被设计成是弱引用,但是value依然是强引用(因为将map的value设置成弱引用时不合理的)。弱引用会在GC时被回收(虽然GC线程优先级不高),而强引用不会,导致出现key=null,value<>null的键值对。导致value出现内存泄漏。虽然,ThreadLocal在调用 set()、get()、remove() 方法的时候,会清理掉 key 为 null 的记录。但是使用完 ThreadLocal方法后最好手动调用remove()方法。
static class Entry extends WeakReference<ThreadLocal<?>> {
/** The value associated with this ThreadLocal. */
Object value;
Entry(ThreadLocal<?> k, Object v) {
super(k);
value = v;
}
}