4.2 set方法(1 ) 源码和对应的中文注释
/*** 设置当前线程对应的ThreadLocal的值** @param value 将要保存在当前线程对应的ThreadLocal的值*/public void set(T value) {// 获取当前线程对象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);}
(2 )代码执行流程
? A. 首先获取当前线程 , 并根据当前线程获取一个Map
? B. 如果获取的Map不为空 , 则将参数设置到Map中(当前ThreadLocal的引用作为key)
? C. 如果Map为空 , 则给该线程创建 Map , 并设置初始值
4.3 remove方法(1 ) 源码和对应的中文注释
/*** 删除当前线程中保存的ThreadLocal对应的实体entry*/public void remove() {// 获取当前线程对象中维护的ThreadLocalMap对象ThreadLocalMap m = getMap(Thread.currentThread());// 如果此map存在if (m != null)// 存在则调用map.remove// 以当前ThreadLocal为key删除对应的实体entrym.remove(this);}
(2 )代码执行流程
? A. 首先获取当前线程 , 并根据当前线程获取一个Map
? B. 如果获取的Map不为空 , 则移除当前ThreadLocal对象对应的entry
4.4 initialValue方法/*** 返回当前线程对应的ThreadLocal的初始值* 此方法的第一次调用发生在 , 当线程通过{@link #get}方法访问此线程的ThreadLocal值时* 除非线程先调用了 {@link #set}方法 , 在这种情况下 , * {@code initialValue} 才不会被这个线程调用 。* 通常情况下 , 每个线程最多调用一次这个方法 。** <p>这个方法仅仅简单的返回null {@code null};* 如果程序员想ThreadLocal线程局部变量有一个除null以外的初始值 , * 必须通过子类继承{@code ThreadLocal} 的方式去重写此方法* 通常, 可以通过匿名内部类的方式实现** @return 当前ThreadLocal的初始值*/protected T initialValue() {return null;}
? 此方法的作用是 返回该线程局部变量的初始值 。
(1) 这个方法是一个延迟调用方法 , 从上面的代码我们得知 , 在set方法还未调用而先调用了get方法时才执行 , 并且仅执行1次 。
(2)这个方法缺省实现直接返回一个null
。
(3)如果想要一个除null之外的初始值 , 可以重写此方法 。(备注: 该方法是一个protected
的方法 , 显然是为了让子类覆盖而设计的)
5. ThreadLocalMap源码分析5.1 基本结构? ThreadLocalMap是ThreadLocal的内部类 , 没有实现Map接口 , 用独立的方式实现了Map的功能 , 其内部的Entry也是独立实现 。

文章插图
(1) 成员变量
/*** 初始容量 —— 必须是2的整次幂*/private static final int INITIAL_CAPACITY = 16;/*** 存放数据的table , Entry类的定义在下面分析* 同样 , 数组长度必须是2的冥 。*/private Entry[] table;/*** 数组里面entrys的个数 , 可以用于判断table当前使用量是否超过负因子 。*/private int size = 0;/*** 进行扩容的阈值 , 表使用量大于它的时候进行扩容 。*/private int threshold; // Default to 0/*** 阈值设置为长度的2/3*/private void setThreshold(int len) {threshold = len * 2 / 3;}
(2) 存储结构 - Entry// 在ThreadLocalMap中 , 也是用Entry来保存K-V结构数据的 。但是Entry中key只能是ThreadLocal对象 , 这点被Entry的构造方法已经限定死了// 另外 , Entry继承WeakReference,使用弱引用 , 可以将ThreadLocal对象的生命周期和线程生命周期解绑 , 持有对ThreadLocal的弱引用 , 可以使得ThreadLocal在没有其他强引用的时候被回收掉 , 这样可以避免因为线程得不到销毁导致ThreadLocal对象无法被回收static class Entry extends WeakReference<ThreadLocal> {/** The value associated with this ThreadLocal. */Object value;Entry(ThreadLocal k, Object v) {super(k);value = https://www.huyubaike.com/biancheng/v;}}
经验总结扩展阅读
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 为啥有的票直达还得换座
- 冰冻的火锅丸子煮多久
- 之八 2流高手速成记:基于Sentinel实现微服务体系下的限流与熔断
- 8k和a3纸的一样大么
- chrome工具调试
- 蓝色糖心玛瑙是天然的吗
- 马克笔和记号笔的区别
- 想开发DAYU200,我教你
- 火车z,k,c,t开头的代表什么?
- 1.5*1.8的床多大 1.5米的床用多大的床单