什么是ThreadLocal?
ThreadLocal提供了线程局部变量,不同线程往ThreadLocal中读写数据的时候是线程隔离的,也就是说线程间是互不影响的。当一个变量需要进行线程隔离的时候,我们就可以考虑使用ThreadLocal。
ThreadLocal的数据存在哪?
每个线程内都绑定了ThreadLocal.ThreadLocalMap,而ThreadLocalMap内部的Entry是ThreadLocal实际存储数据的地方。
class Thread implements Runnable {
// 省略了Thread类的其它代码
/* ThreadLocal values pertaining to this thread. This map is maintained
* by the ThreadLocal class. */
// 和此线程有关的ThreadLocal的值
ThreadLocal.ThreadLocalMap threadLocals = null;
/*
* InheritableThreadLocal values pertaining to this thread. This map is
* maintained by the InheritableThreadLocal class.
*/
ThreadLocal.ThreadLocalMap inheritableThreadLocals = null;
}
ThreadLocal的set()方法:
public void set(T value) {
Thread t = Thread.currentThread();
// 第一次getMap的时候,map都为null
ThreadLocalMap map = getMap(t);
if (map != null)
map.set(this, value);
else
createMap(t, value);
}
void createMap(Thread t, T firstValue) {
t.threadLocals = new ThreadLocalMap(this, firstValue);
}
ThreadLocalMap(ThreadLocal<?> firstKey, Object firstValue) {
table = new Entry[INITIAL_CAPACITY];
int i = firstKey.threadLocalHashCode & (INITIAL_CAPACITY - 1);
table[i] = new Entry(firstKey, firstValue);
size = 1;
setThreshold(INITIAL_CAPACITY);
}
// Get the map associated with a ThreadLocal. Overridden in InheritableThreadLocal.
ThreadLocalMap getMap(Thread t) {
// ThreadLocal.ThreadLocalMap threadLocals = null;
return t.threadLocals;
}
ThreadLocal.get方法
1. 获取当前正在执行的线程
2. 获取当前线程相关的ThreadLocalMap对象
3. ThreadLocalMap对象不为null时,获取ThreadLocalMap静态内部类对象Entry,也即实际存储ThreadLocal值的对象,并从Entry对象中获取存储的值
4. ThreadLocalMap对象null时,获取默认值
public T get() {
// 获取当前正在执行的线程
Thread t = Thread.currentThread();
// 获取当前线程相关的ThreadLocalMap对象
ThreadLocalMap map = getMap(t);
if (map != null) {
// 获取ThreadLocalMap内部类Entry对象,并获取存储的值
ThreadLocalMap.Entry e = map.getEntry(this);
if (e != null) {
@SuppressWarnings("unchecked")
T result = (T)e.value;
return result;
}
}
// 不存在
return setInitialValue();
}
private T setInitialValue() {
T value = initialValue();
Thread t = Thread.currentThread();
ThreadLocalMap map = getMap(t);
if (map != null)
map.set(this, value);
else
createMap(t, value);
return value;
}