/* ThreadLocal values pertaining to this thread. This map is maintained * by the ThreadLocal class. */ ThreadLocal.ThreadLocalMap threadLocals = null;
/* * InheritableThreadLocal values pertaining to this thread. This map is * maintained by the InheritableThreadLocal class. */ ThreadLocal.ThreadLocalMap inheritableThreadLocals = null;
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(); }
set
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
publicvoidset(T value){ Thread t = Thread.currentThread(); ThreadLocalMap map = getMap(t); if (map != null) map.set(this, value); else createMap(t, value); }
ThreadLocalMap getMap(Thread t){ return t.threadLocals; } voidcreateMap(Thread t, T firstValue){ t.threadLocals = new ThreadLocalMap(this, firstValue); }
remove
1 2 3 4 5
publicvoidremove(){ ThreadLocalMap m = getMap(Thread.currentThread()); if (m != null) m.remove(this); }
tab[i] = new Entry(key, value); int sz = ++size; // 清理过期key,判断是否扩容 if (!cleanSomeSlots(i, sz) && sz >= threshold) rehash(); }
key.threadLocalHashCode & (len-1);,斐波那契散列,计算数组下标。
Entry,是一个弱引用对象的实现类,所以在没有外部强引用下,会发生GC,删除key。
for循环判断元素是否存在,当前下标不存在元素时,直接设置元素 tab[i] = new Entry(key, value);。
如果元素存在,则会判断是否key值相等 if (k == key),相等则更新值。
如果不相等,就到了 replaceStaleEntry,探测式清理过期元素。
元素清理 remove
1 2 3 4 5 6 7 8 9 10 11 12 13 14
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); return; } } }
// Rehash until we encounter null Entry e; int i; for (i = nextIndex(staleSlot, len); (e = tab[i]) != null; i = nextIndex(i, len)) { ThreadLocal<?> k = e.get(); if (k == null) { e.value = null; tab[i] = null; size--; } else { int h = k.threadLocalHashCode & (len - 1); if (h != i) { tab[i] = null;
// Unlike Knuth 6.4 Algorithm R, we must scan until // null because multiple entries could have been stale. while (tab[h] != null) h = nextIndex(h, len); tab[h] = e; } } } return i; }
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; }
while 循环中不断的右移进行寻找需要被清理的过期元素,最终都会使用 expungeStaleEntry 进行处理,这里还包括元素的移位。
publicclassInheritableThreadLocal<T> extendsThreadLocal<T> { /** * Computes the child's initial value for this inheritable thread-local * variable as a function of the parent's value at the time the child * thread is created. This method is called from within the parent * thread before the child is started. * <p> * This method merely returns its input argument, and should be overridden * if a different behavior is desired. * * @param parentValue the parent thread's value * @return the child thread's initial value */ protected T childValue(T parentValue){ return parentValue; }
/** * Get the map associated with a ThreadLocal. * * @param t the current thread */ ThreadLocalMap getMap(Thread t){ return t.inheritableThreadLocals; }
/** * Create the map associated with a ThreadLocal. * * @param t the current thread * @param firstValue value for the initial entry of the table. */ voidcreateMap(Thread t, T firstValue){ t.inheritableThreadLocals = new ThreadLocalMap(this, firstValue); } }