ThreadLocal的介绍与运用( 六 )


(1) 这样设计之后每个Map存储的Entry数量就会变少 , 因为之前的存储数量由Thread的数量决定 , 现在是由ThreadLocal的数量决定 。
(2) 当Thread销毁之后 , 对应的ThreadLocalMap也会随之销毁 , 能减少内存的使用 。
4. ThreadLocal的核心方法源码? 基于ThreadLocal的内部结构 , 我们继续探究一下ThreadLocal的核心方法源码 , 更深入的了解其操作原理 。
除了构造之外 ,  ThreadLocal对外暴露的方法有以下4个:
方法声明描述protected T initialValue()返回当前线程局部变量的初始值public void set( T value)设置当前线程绑定的局部变量public T get()获取当前线程绑定的局部变量public void remove()移除当前线程绑定的局部变量其实get , set和remove逻辑是比较相似的 , 我们要研究清楚其中一个 , 其他也就明白了 。
4.1 get方法(1 ) 源码和对应的中文注释
/*** 返回当前线程中保存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获取对应的存储实体eThreadLocalMap.Entry e = map.getEntry(this);// 找到对应的存储实体 eif (e != null) {@SuppressWarnings("unchecked")// 获取存储实体 e 对应的 value值// 即为我们想要的当前线程对应此ThreadLocal的值T result = (T)e.value;return result;}}// 如果map不存在 , 则证明此线程没有维护的ThreadLocalMap对象// 调用setInitialValue进行初始化return setInitialValue();}/*** set的变样实现 , 用于初始化值initialValue , * 用于代替防止用户重写set()方法** @return the initial value 初始化后的值*/private T setInitialValue() {// 调用initialValue获取初始化的值T value = https://www.huyubaike.com/biancheng/initialValue();// 获取当前线程对象Thread t = Thread.currentThread();// 获取此线程对象中维护的ThreadLocalMap对象ThreadLocalMap map = getMap(t);// 如果此map存在if (map != null)// 存在则调用map.set设置此实体entrymap.set(this, value);else// 1)当前线程Thread 不存在ThreadLocalMap对象// 2)则调用createMap进行ThreadLocalMap对象的初始化// 3)并将此实体entry作为第一个值存放至ThreadLocalMap中createMap(t, value);// 返回设置的值valuereturn value;}/*** 获取当前线程Thread对应维护的ThreadLocalMap** @paramt 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是调用此方法的threadLocalt.threadLocals = new ThreadLocalMap(this, firstValue);}(2 )代码执行流程
? A. 首先获取当前线程
? B. 根据当前线程获取一个Map
? C. 如果获取的Map不为空 , 则在Map中以ThreadLocal的引用作为key来在Map中获取对应的value e , 否则转到E
? D. 如果e不为null , 则返回e.value , 否则转到E
? E. Map为空或者e为空 , 则通过initialValue函数获取初始值value , 然后用ThreadLocal的引用和value作为firstKey和firstValue创建一个新的Map
总结:先获取当前线程的 ThreadLocalMap 变量 , 如果存在则返回值 , 不存在则创建并返回初始值 。

经验总结扩展阅读