基于ThreadLocal的内部结构,我们继续分析它的核心方法源码,更深入的了解其操作原理。
除了构造方法之外, ThreadLocal对外暴露的方法有以下4个:
| 方法声明 | 描述 |
| protected T initialValue() | 返回当前线程局部变量的初始值 |
| public void set( T value) | 设置当前线程绑定的局部变量 |
| public T get() | 获取当前线程绑定的局部变量 |
| public void remove() | 移除当前线程绑定的局部变量 |
以下是这4个方法的详细源码分析(为了保证思路清晰, ThreadLocalMap部分暂时不展开,下一个知识点详解)
(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设置此实体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);
- }
(2)代码执行流程
(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获取对应的存储实体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;
- }
(2)代码执行流程
总结: 先获取当前线程的 ThreadLocalMap 变量,如果存在则返回值,不存在则创建并返回初始值。
(1)源码和对应的中文注释
- /**
- * 删除当前线程中保存的ThreadLocal对应的实体entry
- */
- public void remove() {
- // 获取当前线程对象中维护的ThreadLocalMap对象
- ThreadLocalMap m = getMap(Thread.currentThread());
- // 如果此map存在
- if (m != null)
- // 存在则调用map.remove
- // 以当前ThreadLocal为key删除对应的实体entry
- m.remove(this);
- }
(2)代码执行流程
- /**
- * 返回当前线程对应的ThreadLocal的初始值
-
- * 此方法的第一次调用发生在,当线程通过get方法访问此线程的ThreadLocal值时
- * 除非线程先调用了set方法,在这种情况下,initialValue 才不会被这个线程调用。
- * 通常情况下,每个线程最多调用一次这个方法。
- *
- *
这个方法仅仅简单的返回null {@code null};
- * 如果程序员想ThreadLocal线程局部变量有一个除null以外的初始值,
- * 必须通过子类继承{@code ThreadLocal} 的方式去重写此方法
- * 通常, 可以通过匿名内部类的方式实现
- *
- * @return 当前ThreadLocal的初始值
- */
- protected T initialValue() {
- return null;
- }
此方法的作用是 返回该线程局部变量的初始值。