②. set方法详解
- ①. 首先获取当前线程,并根据当前线程获取一个Map
- ②. 如果获取的Map不为空,则将参数设置到Map中(当前ThreadLocal的引用作为key)
- ③. 如果Map为空,则给该线程创建 Map,并设置初始值
/** * 设置当前线程对应的ThreadLocal的值 * * @param value 将要保存在当前线程对应的ThreadLocal的值 */ public void set(T value) { // 获取当前线程对象 Thread t = Thread.currentThread(); // 获取此线程对象中维护的ThreadLocalMap对象 ThreadLocalMap map = getMap(t); // 判断map是否存在 if (map != null) // 存在则调用map.set设置此实体entry map.set(this, value); else // 1)当前线程Thread 不存在ThreadLocalMap对象 // 2)则调用createMap进行ThreadLocalMap对象的初始化 // 3)并将 t(当前线程)和value(t对应的值)作为第一个entry存放至ThreadLocalMap中 createMap(t, value); } /** * 获取当前线程Thread对应维护的ThreadLocalMap * * @param t the current thread 当前线程 * @return the map 对应维护的ThreadLocalMap */ ThreadLocalMap getMap(Thread t) { return t.threadLocals; } /** *创建当前线程Thread对应维护的ThreadLocalMap * * @param t 当前线程 * @param firstValue 存放到map中第一个entry的值 */ void createMap(Thread t, T firstValue) { //这里的this是调用此方法的threadLocal t.threadLocals = new ThreadLocalMap(this, firstValue); } /* * firstKey : 本ThreadLocal实例(this) * firstValue : 要保存的线程本地变量 */ ThreadLocalMap(ThreadLocal<?> firstKey, Object firstValue) { //初始化table table = new ThreadLocal.ThreadLocalMap.Entry[INITIAL_CAPACITY]; //计算索引(重点代码) int i = firstKey.threadLocalHashCode & (INITIAL_CAPACITY - 1); //设置值 table[i] = new ThreadLocal.ThreadLocalMap.Entry(firstKey, firstValue); size = 1; //设置阈值 setThreshold(INITIAL_CAPACITY); }
③. get方法详解
- 先获取当前线程的ThreadLocalMap变量,如果存在则返回值,不存在则创建并返回初始值
/** * 返回当前线程中保存ThreadLocal的值 * 如果当前线程没有此ThreadLocal变量, * 则它会通过调用{@link #initialValue} 方法进行初始化值 * * @return 返回当前线程对应此ThreadLocal的值 */ public T get() { // 获取当前线程对象 Thread t = Thread.currentThread(); // 获取此线程对象中维护的ThreadLocalMap对象 ThreadLocalMap map = getMap(t); // 如果此map存在 if (map != null) { // 以当前的ThreadLocal 为 key,调用getEntry获取对应的存储实体e ThreadLocalMap.Entry e = map.getEntry(this); // 对e进行判空 if (e != null) { @SuppressWarnings("unchecked") // 获取存储实体 e 对应的 value值 // 即为我们想要的当前线程对应此ThreadLocal的值 T result = (T)e.value; return result; } } /* 初始化 : 有两种情况有执行当前代码 第一种情况: map不存在,表示此线程没有维护的ThreadLocalMap对象 第二种情况: map存在, 但是没有与当前ThreadLocal关联的entry */ return setInitialValue(); } /** * 初始化 * * @return the initial value 初始化后的值 */ private T setInitialValue() { // 调用initialValue获取初始化的值 // 此方法可以被子类重写, 如果不重写默认返回null T value = initialValue(); // 获取当前线程对象 Thread t = Thread.currentThread(); // 获取此线程对象中维护的ThreadLocalMap对象 ThreadLocalMap map = getMap(t); // 判断map是否存在 if (map != null) // 存在则调用map.set设置此实体entry map.set(this, value); else // 1)当前线程Thread 不存在ThreadLocalMap对象 // 2)则调用createMap进行ThreadLocalMap对象的初始化 // 3)并将 t(当前线程)和value(t对应的值)作为第一个entry存放至ThreadLocalMap中 createMap(t, value); // 返回设置的值value return value; }
④. remove方法详解
- ①. 首先获取当前线程,并根据当前线程获取一个Map
- ②. 如果获取的Map不为空,则移除当前ThreadLocal对象对应的entry
/** * 删除当前线程中保存的ThreadLocal对应的实体entry */ public void remove() { // 获取当前线程对象中维护的ThreadLocalMap对象 ThreadLocalMap m = getMap(Thread.currentThread()); // 如果此map存在 if (m != null) // 存在则调用map.remove // 以当前ThreadLocal为key删除对应的实体entry m.remove(this); }