/**
* Construct a new map initially containing (firstKey, firstValue).
* ThreadLocalMaps are constructed lazily, so we only create
* one when we have at least one entry to put in it.
*/
ThreadLocalMap(ThreadLocal<?> firstKey, Object firstValue) {
table = new Entry[INITIAL_CAPACITY];
int i = firstKey.threadLocalHashCode & (INITIAL_CAPACITY - 1);
table = new Entry(firstKey, firstValue);
size = 1;
setThreshold(INITIAL_CAPACITY);
}
1.创建了一个Entry数组,初始化大小为16。
// We don't use a fast path as with get() because it is at
// least as common to use set() to create new entries as
// it is to replace existing ones, in which case, a fast
// path would fail more often than not.
Entry[] tab = table;
int len = tab.length;
int i = key.threadLocalHashCode & (len-1);
for (Entry e = tab;
e != null;
e = tab[i = nextIndex(i, len)]) {
ThreadLocal<?> k = e.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();
}
get方法体前两行和set方法一样,接下来分2种情况:
1.map为空,直接调用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;
}
setInitialValue方法体第一行调用initialValue方法(如下面代码所示),这个方法直接返回null赋值给value;接下来还是获取map,此时map是为空的,所以调用creatMap方法创建新的ThreadLocalMap对象。最后直接返回null。
protected T initialValue() {
return null;
}
2.map不为空,通过map调用getEntry方法,传入的参数是当前ThreadLocal对象,getEntry方法如下:
private Entry getEntry(ThreadLocal<?> key) {
int i = key.threadLocalHashCode & (table.length - 1);
Entry e = table;
if (e != null && e.get() == key)
return e;
else
return getEntryAfterMiss(key, i, e);
}
首先通过keyhash计算获取数组下标再拿到Entry元素e,判断e不等于null而且e元素的key等于当前传入的ThreadLocal对象,直接返回e;否则执行getEntryAfterMiss方法:
private Entry getEntryAfterMiss(ThreadLocal<?> key, int i, Entry e) {
Entry[] tab = table;
int len = tab.length;
while (e != null) {
ThreadLocal<?> k = e.get();
if (k == key)
return e;
if (k == null)
expungeStaleEntry(i);
else
i = nextIndex(i, len);
e = tab;
}
return null;
}
这个getEntryAfterMiss方法个人认为做了三件事:
1.通过while循环解决hash冲突
2.判断是否有陈旧元素,有的话将其删除
3.拿到最终元素e返回
最后,get方法拿到元素e后,调用e.value获取value值返回。至此,get方法分析结束
3.3remove方法
先上源码:
public void remove() {
ThreadLocalMap m = getMap(Thread.currentThread());
if (m != null)
m.remove(this);
}
相当于执行ThreadLocalMap的remove方法:
/**
* Remove the entry for key.
*/
private void remove(ThreadLocal<?> key) {
Entry[] tab = table;
int len = tab.length;
int i = key.threadLocalHashCode & (len-1);
for (Entry e = tab;
e != null;
e = tab[i = nextIndex(i, len)]) {
if (e.get() == key) {
e.clear();
expungeStaleEntry(i);
return;
}
}
}
for循环是为了解决hash冲突,解决hash冲突就是将i+1,如果e元素的key等于当前传入的ThreadLocal对象,那么就清空这个元素。结束