// 直到为null的位置,都没遇到上面的情况,则就地新建Entry,然后尝试删除过期的Entry,没有则检查是否需要扩容 tab[i] = new Entry(key, value); int sz = ++size; if (!cleanSomeSlots(i, sz) && sz >= threshold) // 这里保证了每次set一定能找到空位置 rehash(); }
// 向后环型遍历 privatestaticintnextIndex(int i, int len){ return ((i + 1 < len) ? i + 1 : 0); }
privatevoidreplaceStaleEntry(ThreadLocal<?> key, Object value, int staleSlot){ Entry[] tab = table; int len = tab.length; Entry e;
// 向前环形遍历直至为null,找到最前面过期Entry的位置,并记为slotToExpunge,作为下面清理的起点 // 这样做是因为如果出现了过期Entry,则大概率在其附近还会有其它过期的Entry,毕竟GC时是平等的,没有只针对哪个 int slotToExpunge = staleSlot; for (int i = prevIndex(staleSlot, len); (e = tab[i]) != null; i = prevIndex(i, len)) if (e.get() == null) slotToExpunge = i;
// 向后环形遍历直至为null for (int i = nextIndex(staleSlot, len); (e = tab[i]) != null; 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(); }
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; }
private Entry getEntry(ThreadLocal<?> key){ int i = key.threadLocalHashCode & (table.length - 1); Entry e = table[i]; if (e != null && e.get() == key) return e; else return getEntryAfterMiss(key, i, e); }
private Entry getEntryAfterMiss(ThreadLocal<?> key, int i, Entry e){ Entry[] tab = table; int len = tab.length;
while (e != null) { // 向后环形遍历,直至为null ThreadLocal<?> k = e.get(); if (k == key) // 找到了直接返回 return e; if (k == null) // 过期Entry则帮忙清理,与上面一样 expungeStaleEntry(i); else i = nextIndex(i, len); e = tab[i]; } returnnull; // 没有这个hash对应的ThreadLocal,直接返回null }
2.3. remove
java.lang.ThreadLocal
1 2 3 4 5
publicvoidremove(){ ThreadLocalMap m = getMap(Thread.currentThread()); if (m != null) m.remove(this); }
java.lang.ThreadLocal.ThreadLocalMap
1 2 3 4 5 6 7 8 9 10 11 12
privatevoidremove(ThreadLocal<?> key){ Entry[] tab = table; int len = tab.length; int i = key.threadLocalHashCode & (len-1); for (Entry e = tab[i]; e != null; e = tab[i = nextIndex(i, len)]) { if (e.get() == key) { e.clear(); expungeStaleEntry(i); // 清除当前Entry,并尝试继续向后清除过期Entry,直至为null的位置返回 return; } } }