# ThreadLocal 的原理是什么,使用场景有哪些
ThreadLocal 类中有两个变量 threadLocals 和 inheritableThreadLocals,二者都是 ThreadLocal 内部类 ThreadLocalMap 类型的变量,我们通过查看内部类 ThreadLocalMap 可以发现实际上它类似于一个 HashMap。在默认情况下,每个线程中的这两个变量都为 null:
ThreadLocal.ThreadLocalMap threadLocals = null;
ThreadLocal.ThreadLocalMap inheritableThreadLocals = null;
只有当线程第一次调用 ThreadLocal 的 set 或者 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(); | |
} | |
ThreadLocalMap getMap(Thread t) { | |
return t.threadLocals; | |
} |
除此之外,每个线程的本地变量不是存放在 ThreadLocal 实例中,而是放在调用线程的 ThreadLocals 变量里面。也就是说,ThreadLocal 类型的本地变量是存放在具体的线程空间上,其本身相当于一个装载本地变量的载体,通过 set 方法将 value 添加到调用线程的 threadLocals 中,当调用线程调用 get 方法时候能够从它的 threadLocals 中取出变量。如果调用线程一直不终止,那么这个本地变量将会一直存放在他的 threadLocals 中,所以不使用本地变量的时候需要调用 remove 方法将 threadLocals 中删除不用的本地变量,防止出现内存泄漏。
public void set(T value) { | |
Thread t = Thread.currentThread(); | |
ThreadLocalMap map = getMap(t); | |
if (map != null) | |
map.set(this, value); | |
else | |
createMap(t, value); | |
} | |
public void remove() { | |
ThreadLocalMap m = getMap(Thread.currentThread()); | |
if (m != null) | |
m.remove(this); | |
} |