这里有一个注意点
int i = key.threadLocalHashCode & (len-1);
下标是通过 hash 来确定的,会出现 hash 冲突,这里采用的是开放地址法来解决 hash 冲突,在下面的代码中有判断
k==key
,如果不相等则
nextIndex(i, len)
获取下一个下标来判断。
上述就是整个
set
的过程,下面来看一下
get
public T get(){ Thread t = Thread.currentThread(); // 获取当前线程的ThreadLocalMap ThreadLocalMap map = getMap(t); if (map != null) { // this为当前threadLocal,获取对应的entry ThreadLocalMap.Entry e = map.getEntry(this); if (e != null) { // 返回当前entry的值即可。 @SuppressWarnings("unchecked") T result = (T)e.value; return result; } } // 设置初始值并返回,初始值是null return setInitialValue(); }
private Entry getEntry(ThreadLocal> key){ // 查找下标 int i = key.threadLocalHashCode & (table.length - 1); Entry e = table[i]; if (e != null && e.get() == key) // 找到对应entry进行返回 return e; else // 开始遍历entry数组,如果能找到key的entry就返回否则返回null return getEntryAfterMiss(key, i, e); }
get
方法要比
set
简单很多,只是根据 key 找对应 entry,把 entry 的值返回即可。
if (!cleanSomeSlots(i, sz) && sz >= threshold) rehash();
该方法的具体代码如下:
privatebooleancleanSomeSlots(int i, int n){ boolean removed = false; Entry[] tab = table; int len = tab.length; do { i = nextIndex(i, len); Entry e = tab[i]; if (e != null && e.get() == null) { n = len; removed = true; i = expungeStaleEntry(i); } } while ( (n >>>= 1) != 0); return removed; }