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 = 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 = 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 }
ThreadLocal源码学习,布布扣,bubuko.com
时间: 2024-10-01 02:49:09