(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 变量 , 如果存在则返回值 , 不存在则创建并返回初始值 。
经验总结扩展阅读
- 为啥有的票直达还得换座
- 冰冻的火锅丸子煮多久
- 之八 2流高手速成记:基于Sentinel实现微服务体系下的限流与熔断
- 8k和a3纸的一样大么
- chrome工具调试
- 蓝色糖心玛瑙是天然的吗
- 马克笔和记号笔的区别
- 想开发DAYU200,我教你
- 火车z,k,c,t开头的代表什么?
- 1.5*1.8的床多大 1.5米的床用多大的床单