This class provides thread-local variables. These variables differ from their normal counterparts in that each thread that accesses one (via its get or set method) has its own, independently initialized copy of the variable. ThreadLocal instances are typically private static fields in classes that wish to associate state with a thread (e.g., a user ID or Transaction ID). Each thread holds an implicit reference to its copy of a thread-local variable as long as the thread is alive and the ThreadLocal instance is accessible; after a thread goes away, all of its copies of thread-local instances are subject to garbage collection (unless other references to these copies exist).
public void set(T value) { Thread t = Thread.currentThread(); // 获取当前线程 ThreadLocalMap map = getMap(t); // 获取线程对应映射表 if (map != null) // 设置KV map.set(this, value); else createMap(t, value); }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
public T get() { Thread t = Thread.currentThread(); ThreadLocalMap map = getMap(t); if (map != null) { // 获取映射表中当前ThreadLocal对应的Value ThreadLocalMap.Entry e = map.getEntry(this); if (e != null) { @SuppressWarnings("unchecked") T result = (T)e.value; return result; } } // 如果Map还未初始化或者Map中没有找到Key,则设置一个初始值 return setInitialValue(); }
/** * 初始化容量,必须是2的幂次方 */ private static final int INITIAL_CAPACITY = 16;
/** * 哈希表,长度为2的幂次方 */ private Entry[] table;
/** * The number of entries in the table.(Entry数目) */ private int size = 0;
/** * 记录下一次扩容阀值 */ private int threshold; // Default to 0
/** * Set the resize threshold to maintain at worst a 2/3 load factor.(设置下一次阀值,len的三分之二) */ private void setThreshold(int len) { threshold = len * 2 / 3; }
/** * Increment i modulo len.(以len为模增加i) */ private static int nextIndex(int i, int len) { return ((i + 1 < len) ? i + 1 : 0); }
/** * Decrement i modulo len.(以len为模减少i) */ private static int prevIndex(int i, int len) { return ((i - 1 >= 0) ? i - 1 : len - 1); }
// 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); //取index值 // nextIndex方法实现全遍历 for (Entry e = tab[i]; e != null; e = tab[i = nextIndex(i, len)]) { ThreadLocal<?> k = e.get();