ThreadLocal是一个java类,它可以保存当前线程的变量,让每个线程都有一份自己的副本变量,多个线程互不干扰。
ThreadLocal中的set方法:
public void set(T value) {
Thread t = Thread.currentThread();
ThreadLocalMap map = getMap(t);
if (map != null)
map.set(this, value);
else
createMap(t, value);
}
set方法会传入一个参数value,这个value会存到一个ThreadLocalMap类型的对象中。
然后查看getMap方法(下示),可以得出这个map对象就是当前线程Thread的一个成员变量threadLocals.
/**
* Get the map associated with a ThreadLocal. Overridden in
* InheritableThreadLocal.
*
* @param t the current thread
* @return the map
*/
ThreadLocalMap getMap(Thread t) {
return t.threadLocals;
}
所以可以得出:我们每次往ThreadLocal中set值就是存入了当前线程对象的threadLocals属性中,而这个threadLocals属性的类型是ThreadLocalMap,它就类似于一个HashMap.
ThreadLocal中get方法:
public T get() {
Thread t = Thread.currentThread();
ThreadLocalMap map = getMap(t);
if (map != null) {
ThreadLocalMap.Entry e = map.getEntry(this);
if (e != null) {
@SuppressWarnings("unchecked")
T result = (T)e.value;
return result;
}
}
return setInitialValue();
}
与set方法一样,也是根据当前线程获取ThreadLocalMap对象,然后再从map中取值。
ThreadLocalMap是ThreadLocal的一个静态内部类(下示)
ThreadLocalMap是由Entry对象构成
由上代码知Entry又继承自WeakReference
因此它会产生内存泄漏问题:在一次GC中,弱引用key会被回收掉,而强引用value不会被回收,因此就会出现Entry中的value对应的key为null,导致这个value无法被访问到,此时这个value也无法被回收,就造成了内存泄漏。
(内存泄漏:程序中已动态分配的堆内存由于某种原因而导致程序未释放或无法释放,造成系统内存的浪费,导致程序运行速度减慢甚至系统崩溃等严重后果)
解决方法:在不使用时,主动调用remove方法进行清理