//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). public class ThreadLocal<T> { ... ... }
public class ThreadLocal<T> { ... //初始化线程Thread的成员变量ThreadLocalMap void createMap(Thread t, T firstValue) { //这里的this是调用此方法的threadLocal对象 //初始化ThreadLocalMap的第一个元素,key为调用此方法的threadLocal对象,value为传入的firstValue t.threadLocals = new ThreadLocalMap(this, firstValue); } //ThreadLocalMap is a customized hash map suitable only for maintaining thread local values. //No operations are exported outside of the ThreadLocal class. //The class is package private to allow declaration of fields in class Thread. //To help deal with very large and long-lived usages, the hash table entries use WeakReferences for keys. //However, since reference queues are not used, //stale entries are guaranteed to be removed only when the table starts running out of space. static class ThreadLocalMap { //The entries in this hash map extend WeakReference, //using its main ref field as the key (which is always a ThreadLocal object). //Note that null keys (i.e. entry.get() == null) mean that the key is no longer referenced, //so the entry can be expunged from table. //Such entries are referred to as "stale entries" in the code that follows. static class Entry extends WeakReference<ThreadLocal<?>> { //The value associated with this ThreadLocal. Object value; Entry(ThreadLocal<?> k, Object v) { super(k); value = v; } } //The initial capacity -- MUST be a power of two. private static final int INITIAL_CAPACITY = 16; //The table, resized as necessary. //table.length MUST always be a power of two. private Entry[] table; //The number of entries in the table. private int size = 0; ThreadLocalMap(ThreadLocal<?> firstKey, Object firstValue) { //初始化一个长度为16的Entry数组 table = new Entry[INITIAL_CAPACITY]; //通过对firstKey这个ThreadLocal实例对象的hashCode,进行位运算取模,来得到一个数组下标i int i = firstKey.threadLocalHashCode & (INITIAL_CAPACITY - 1); //将firstKey和firstValue封装成一个Entry对象,保存到数组的下标为i的位置 table[i] = new Entry(firstKey, firstValue); size = 1; setThreshold(INITIAL_CAPACITY); } ... } ... } public class Thread implements Runnable { ... //每个线程都有一个ThreadLocalMap类型的成员变量,叫threadLocals ThreadLocal.ThreadLocalMap threadLocals = null; ... }
public class ThreadLocal<T> { ... static class ThreadLocalMap { //The entries in this hash map extend WeakReference, //using its main ref field as the key (which is always a ThreadLocal object). //Note that null keys (i.e. entry.get() == null) mean that the key is no longer referenced, //so the entry can be expunged from table. //Such entries are referred to as "stale entries" in the code that follows. static class Entry extends WeakReference<ThreadLocal<?>> { //The value associated with this ThreadLocal. Object value; Entry(ThreadLocal<?> k, Object v) { super(k); value = v; } } //The initial capacity -- MUST be a power of two. private static final int INITIAL_CAPACITY = 16; //The table, resized as necessary. //table.length MUST always be a power of two. private Entry[] table; //The number of entries in the table. private int size = 0; ThreadLocalMap(ThreadLocal<?> firstKey, Object firstValue) { //初始化一个长度为16的Entry数组 table = new Entry[INITIAL_CAPACITY]; //通过对firstKey这个ThreadLocal实例对象的hashCode,进行位运算取模,来得到一个数组下标i int i = firstKey.threadLocalHashCode & (INITIAL_CAPACITY - 1); //将firstKey和firstValue封装成一个Entry对象,保存到数组的下标为i的位置 table[i] = new Entry(firstKey, firstValue); size = 1; setThreshold(INITIAL_CAPACITY); } //Set the value associated with key. //@param key the thread local object //@param value the value to be set private void set(ThreadLocal<?> key, Object value) { Entry[] tab = table; int len = tab.length; //首先根据ThreadLocal对象的hashCode和数组长度进行位与运算(即取模),来获取元素放置的位置(即数组下标) int i = key.threadLocalHashCode & (len-1); //然后从i开始往后遍历到数组最后一个Entry(线性探索) for (Entry e = tab[i]; e != null; e = tab[i = nextIndex(i, len)]) { //获取Entry元素中的key ThreadLocal<?> k = e.get(); //如果key相等,则覆盖value if (k == key) { e.value = value; return; } //如果key为null,则用新key、value覆盖 //同时清理key = null的陈旧数据(弱引用) if (k == null) { replaceStaleEntry(key, value, i); return; } } //如果数组下标i的位置不存在数据,则直接将key和value封装成Entry对象存储到该位置 tab[i] = new Entry(key, value); int sz = ++size; //如果超过阈值,就需要扩容了,cleanSomeSlots()方法会清理数组中的无效的key if (!cleanSomeSlots(i, sz) && sz >= threshold) { rehash();//扩容 } } private static int nextIndex(int i, int len) { return ((i + 1 < len) ? i + 1 : 0); } ... } ... }
public class ThreadLocal<T> { ... static class ThreadLocalMap { private Entry[] table; static class Entry extends WeakReference<ThreadLocal<?>> { //The value associated with this ThreadLocal. Object value; Entry(ThreadLocal<?> k, Object v) { super(k); value = v; } } ... } }