建网站 pdf,WordPress如何推广,山西住房与城乡建设厅定额网站,网站开发的微端基于ThreadLocal的内部结构#xff0c;我们继续分析它的核心方法源码#xff0c;更深入的了解其操作原理。
除了构造方法之外#xff0c; ThreadLocal对外暴露的方法有以下4个#xff1a;
方法声明描述protected T initialValue()返回当前线程局部变量的初始值public voi…基于ThreadLocal的内部结构我们继续分析它的核心方法源码更深入的了解其操作原理。
除了构造方法之外 ThreadLocal对外暴露的方法有以下4个
方法声明描述protected T initialValue()返回当前线程局部变量的初始值public void set( T value)设置当前线程绑定的局部变量public T get()获取当前线程绑定的局部变量public void remove()移除当前线程绑定的局部变量
以下是这4个方法的详细源码分析(为了保证思路清晰, ThreadLocalMap部分暂时不展开,下一个知识点详解) 1 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并将 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是调用此方法的threadLocalt.threadLocals new ThreadLocalMap(this, firstValue);} 2代码执行流程
首先获取当前线程并根据当前线程获取一个Map如果获取的Map不为空则将参数设置到Map中当前ThreadLocal的引用作为key如果Map为空则给该线程创建 Map并设置初始值 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 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代码执行流程
首先获取当前线程, 根据当前线程获取一个Map如果获取的Map不为空则在Map中以ThreadLocal的引用作为key来在Map中获取对应的Entry e否则转到D如果e不为null则返回e.value否则转到DMap为空或者e为空则通过initialValue函数获取初始值value然后用ThreadLocal的引用和value作为firstKey和firstValue创建一个新的Map
总结: 先获取当前线程的 ThreadLocalMap 变量如果存在则返回值不存在则创建并返回初始值。 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代码执行流程
首先获取当前线程并根据当前线程获取一个Map如果获取的Map不为空则移除当前ThreadLocal对象对应的entry 4 initialValue方法 /*** 返回当前线程对应的ThreadLocal的初始值* 此方法的第一次调用发生在当线程通过get方法访问此线程的ThreadLocal值时* 除非线程先调用了set方法在这种情况下initialValue 才不会被这个线程调用。* 通常情况下每个线程最多调用一次这个方法。** p这个方法仅仅简单的返回null {code null};* 如果程序员想ThreadLocal线程局部变量有一个除null以外的初始值* 必须通过子类继承{code ThreadLocal} 的方式去重写此方法* 通常, 可以通过匿名内部类的方式实现** return 当前ThreadLocal的初始值*/
protected T initialValue() {return null;
} 此方法的作用是 返回该线程局部变量的初始值。
这个方法是一个延迟调用方法从上面的代码我们得知在set方法还未调用而先调用了get方法时才执行并且仅执行1次。这个方法缺省实现直接返回一个null。如果想要一个除null之外的初始值可以重写此方法。备注 该方法是一个protected的方法显然是为了让子类覆盖而设计的