// 根据 ThreadLocal 的散列值,查找对应元素在数组中的位置
int i = key.threadLocalHashCode & (len-1);
// 采用“线性探测法”,寻找合适位置
for (Entry e = tab[i];
e != null;
e = tab[i = nextIndex(i, len)]) {
ThreadLocal<?> k = e.get();
// 若key 存在,直接覆盖
if (k == key) {
e.value = value;
return;
}
// key == null,但是存在值(因为此处的e != null),说明之前的ThreadLocal对象已经被回收了
if (k == null) {
// 用新元素替换陈旧的元素
replaceStaleEntry(key, value, i);
return;
}
}
//创建新元素
tab[i] = new Entry(key, value);
int sz = ++size;
// 如果没有清理陈旧的 Entry 并且数组中的元素大于了阈值,则进行 rehash
if (!cleanSomeSlots(i, sz) && sz >= threshold)
rehash();
}
2、核心方法解析
(1) get()
返回此线程局部变量的当前线程副本中的值
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();
}
首先通过当前线程获取所对应的成员变量ThreadLocalMap
,然后通过ThreadLocalMap
获取当前ThreadLocal
的Entry
,最后通过所获取的Entry获取目标值result
。
(2) set(T value)
将此线程局部变量的当前线程副本中的值设置为指定值。
public void set(T value) {
Thread t = Thread.currentThread();
ThreadLocalMap map = getMap(t);
if (map != null)
map.set(this, value);
else
createMap(t, value);
}
获取当前线程所对应的ThreadLocalMap
,如果不为空,则调用ThreadLocalMap
的set()
方法,key就是当前ThreadLocal
,如果不存在,则调用createMap()
方法新建一个。
void createMap(Thread t, T firstValue) {
t.threadLocals = new ThreadLocalMap(this, firstValue);
}
(3) initialValue()
返回此线程局部变量的当前线程的初始值。
protected T initialValue() {
return null;
}
该方法定义为protected
级别且返回为null
,需要其子类实现其功能,所以我们在使用ThreadLocal
的时候一般都应该覆盖该方法。该方法不能显示调用,只有在第一次调用get()
或者set()
方法时才会被执行,并且仅执行1次。
(4) remove()
移除此线程局部变量当前线程的值。
public void remove() {
ThreadLocalMap m = getMap(Thread.currentThread());
if (m != null)
m.remove(this);
}
1、多个线程去获取一个共享变量时,要求获取的是这个变量的初始值的副本。每个线程存储这个变量的副本,对这个变量副本的改变不会影响变量本身。适用于多个线程依赖不同变量值完成操作的场景。比如: