首页 > 代码库 > ThreadLocal源码学习

ThreadLocal源码学习

ThreadLocal,线程本地化对象,在多线程环境中,使用ThreadLocal对象来维护变量时,ThreadLocal为每个使用该变量的线程维护一个独立的线程副本。

ThreadLocal.java源文件内容为:

  1 /**  2   * ThreadLocal内部包含一个用数组实现的哈希表,用来存储对应到每个线程的局部对象的值  3   * 其中,ThreadLocal对象担当key,实际通过threadLocalHashCode值来进行检索  4   */  5 public class ThreadLocal<T> {  6     //其中 T 类型代表的是被多个线程访问的局部变量类型  10     private final int threadLocalHashCode = nextHashCode();  11     /**  12     * Returns the current thread‘s "initial value" for this  13     * thread-local variable. This method will be invoked the first  14     * time a thread accesses the variable with the {@link #get}  15     * method, unless the thread previously invoked the {@link #set}  16     * method, in which case the <tt>initialValue</tt> method will not  17     * be invoked for the thread. Normally, this method is invoked at  18     * most once per thread, but it may be invoked again in case of  19     * subsequent invocations of {@link #remove} followed by {@link #get}.  20     * * <p>This implementation simply returns <tt>null</tt>; if the  21     * programmer desires thread-local variables to have an initial  22     * value other than <tt>null</tt>, <tt>ThreadLocal</tt> must be  23     * subclassed, and this method overridden. Typically, an  24     * anonymous inner class will be used.  25     * * @return the initial value for this thread-local(返回当前线程局部对象的初始值)  26     */  27     protected T initialValue() {  28         //protected成员,期望被子类继承  29         return null;  30     }  31     /**  32     * 返回在当前线程中的线程局部对象的值,  33     * 若线程局部对象对于当前线程没有值,则被初始化微 initialValue方法的返回值  34     */  35     public T get() {  36         Thread t = Thread.currentThread();  37         ThreadLocalMap map = getMap(t);  38         if (map != null) {  39             ThreadLocalMap.Entry e = map.getEntry(this);  40             if (e != null)  41                 return (T)e.value;  42         }  43  44             return setInitialValue();  45     }  46  47     /**  48     * Sets the current thread‘s copy of this thread-local variable  49     * to the specified value. Most subclasses will have no need to  50     * override this method, relying solely on the method to set the values of thread-locals.  51     */  52     public void set(T value) {  53         Thread t = Thread.currentThread();  54         ThreadLocalMap map = getMap(t);  55         if (map != null)  56             //以当前线程对象为key,设置当前局部对象的值 57             map.set(this, value);  58         else  59             createMap(t, value);  60     }  61  62     /**  63     * Removes the current thread‘s value for this thread-local  64     * variable. If this thread-local variable is subsequently  65     * {@linkplain #get read} by the current thread, its value will be  66     * reinitialized by invoking its {@link #initialValue} method,  67     * unless its value is {@linkplain #set set} by the current thread  68     * in the interim. This may result in multiple invocations of the  69     * <tt>initialValue</tt> method in the current thread.  70     */  71     public void remove() {  72         ThreadLocalMap m = getMap(Thread.currentThread());  73         if (m != null)  74             //从ThreadLocalMap中移除对象 75             m.remove(this);  76     }  77  78     /**  79     * Get the map associated with a ThreadLocal. Overridden in  80     * InheritableThreadLocal.  81     * * @param t the current thread  82     * @return the map  83     */  84     ThreadLocalMap getMap(Thread t) {  85         //返回当前Threadlocal相关的ThreadLocalMap对象  86         return t.threadLocals;  87     }  88  89     /**  90     * Create the map associated with a ThreadLocal. Overridden in  91     * InheritableThreadLocal.  92     * * @param t the current thread  93     * @param firstValue value for the initial entry of the map  94     * @param map the map to store.  95     */  96     void createMap(Thread t, T firstValue) {  97         t.threadLocals = new ThreadLocalMap(this, firstValue); //为当前线程创建关联的ThreadLocalMap对象  98     }  99 100     //ThreadLocalMap是一个定制的只能用来存储线程局部对象的哈希映射 101     //使用弱引用来当做key,只有当表空间不够时,旧的对象才会被移除 102     static class ThreadLocalMap { 103         //ThreadLocalMap的内部数组的元素类型:使用对ThreadLocal的弱引用类型来作为元素类型 104         static class Entry extends WeakReference<ThreadLocal> { 105         /** 106         * The value associated with this ThreadLocal. 107         */ 108         Object value; 109 110         Entry(ThreadLocal k, Object v) { 111             super(k); 112             value =http://www.mamicode.com/ v; 113         } 114     } 115 116     //哈希表的初始大小 117     private static final int INITIAL_CAPACITY = 16; 118 119     /** 120     * 用于存储ThreadLocal弱引用的数组 121     */ 122     private Entry[] table; 123 124     //ThreadLocalMap使用延迟初始化,当我们需要向ThreadLocalMap中放元素时,才会初始化它 125     ThreadLocalMap(ThreadLocal firstKey, Object firstValue) { 126         table = new Entry[INITIAL_CAPACITY]; 127         int i = firstKey.threadLocalHashCode & (INITIAL_CAPACITY - 1); 128         table[i] = new Entry(firstKey, firstValue); //初始时,使用ThreadLocal.threadLocalHashCode作为哈希表的哈希值 size = 1; 129 130         //设定ThreadLocalMap中元素个数 131         setThreshold(INITIAL_CAPACITY); 132     } 133 134     /** 135     * Set the value associated with key. 136     * * @param key the thread local object 137     * @param value the value to be set 138     */ 139     private void set(ThreadLocal key, Object value) { 140         // We don‘t use a fast path as with get() because it is at 141         // least as common to use set() to create new entries as 142         // it is to replace existing ones, in which case, a fast 143         // path would fail more often than not. 144         Entry[] tab = table; 145         int len = tab.length; 146         int i = key.threadLocalHashCode & (len-1); 147         for (Entry e = tab[i]; e != null; e = tab[i = nextIndex(i, len)]) { 148             ThreadLocal k = e.get(); 149             if (k == key) { 150                 e.value =http://www.mamicode.com/ value; 151                 return; 152             } 153 154             if (k == null) { 155                 replaceStaleEntry(key, value, i); 156                 return;157             } 158         } 159 160         tab[i] = new Entry(key, value); 161         int sz = ++size; 162         if (!cleanSomeSlots(i, sz) && sz >= threshold) 163             rehash(); 164     } 165 166     /** 167     * Remove the entry for key. 168     */ 169     private void remove(ThreadLocal key) { 170         Entry[] tab = table; 171         int len = tab.length; 172         int i = key.threadLocalHashCode & (len-1); 173         for (Entry e = tab[i]; e != null; e = tab[i = nextIndex(i, len)]) { 174             if (e.get() == key) { 175                 e.clear(); 176                 expungeStaleEntry(i); 177                 return; 178             } 179         } 180     } 181 }