深入解析ThreadLocal( 七 )


C. 如果Map为空 , 则给该线程创建 Map , 并设置初始值
4.2 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);// 对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获取初始化的值// 此方法可以被子类重写, 如果不重写默认返回nullT value = http://kandian.youth.cn/index/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)并将 t(当前线程)和value(t对应的值)作为第一个entry存放至ThreadLocalMap中createMap(t, value);// 返回设置的值valuereturn value;}(2 ) 代码执行流程
A. 首先获取当前线程, 根据当前线程获取一个Map
B. 如果获取的Map不为空 , 则在Map中以ThreadLocal的引用作为key来在Map中获取对应的Entry e , 否则转到D
C. 如果e不为null , 则返回e.value , 否则转到D
D. Map为空或者e为空 , 则通过initialValue函数获取初始值value , 然后用ThreadLocal的引用和value作为firstKey和firstValue创建一个新的Map
总结: 先获取当前线程的 ThreadLocalMap 变量 , 如果存在则返回值 , 不存在则创建并返回初始值 。
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的初始值* 此方法的第一次调用发生在 , 当线程通过get方法访问此线程的ThreadLocal值时* 除非线程先调用了set方法 , 在这种情况下 , initialValue 才不会被这个线程调用 。* 通常情况下 , 每个线程最多调用一次这个方法 。** 这个方法仅仅简单的返回null {@code null};* 如果程序员想ThreadLocal线程局部变量有一个除null以外的初始值 ,* 必须通过子类继承{@code ThreadLocal} 的方式去重写此方法* 通常, 可以通过匿名内部类的方式实现** @return 当前ThreadLocal的初始值*/protected T initialValue() {return null;}


推荐阅读