上一篇文章中对ThreadLocal进行了详尽的介绍,另外还有一个类:
InheritableThreadLocal
他是ThreadLocal的子类,那么这个类又有什么做用呢?
测试代码
public class T25 {
public static void main(String[] args) {
//主线程中赋值
ThreadLocal<String> stringThreadLocal = new ThreadLocal<>();
InheritableThreadLocal<String> stringInheritableThreadLocal = new InheritableThreadLocal<>();
stringThreadLocal.set("ThreadLocal string");
stringInheritableThreadLocal.set("InheritableThreadLocal string");
//子线程中分别打印两个变量的信息
new Thread(() -> {
System.out.println(
Thread.currentThread().getName() + " ThreadLocal value :" + stringThreadLocal.get());
System.out.println(Thread.currentThread().getName() + " InheritableThreadLocal value :"
+ stringInheritableThreadLocal.get());
}).start();
}
}
在上面的测试代码中,主线程中建立了两个变量,类型分别为:ThreadLocal和InheritableThreadLocal
而后在主线程中建立了一个新的线程
在新的线程中,尝试获取他们的值
从打印信息能够看得出来
对于ThreadLocal获取的值为null,而对于InheritableThreadLocal则可以获取到值
结论:
在子线程中,能够获取到父线程的InheritableThreadLocal类型变量的值,而不能获取到ThreadLocal类型变量的值
对于ThreadLocal咱们已经有了详尽的分析,在Thread中有一个map,以ThreadLocal类型的变量做为key
在子线程中,get方法天然是获取子线程中的map,很显然,子线程中的map并无设置任何值,因此初始值null被读取出来
可是,InheritableThreadLocal为何可以读取出来?
原理分析
在Thread类中,有一个ThreadLocal.ThreadLocalMap类型的变量:inheritableThreadLocals,他的类型同Thread内部的threadLocals变量
在Thread的init方法中,有一段初始化设置(应该还记得,这个init方法是全部的Thread对象建立的必经之路)
下面为部分代码片断拼接
从上面的这个方法能够很清晰的看获得
若是parent的inheritableThreadLocals不是null,那么就会将当前线程的inheritableThreadLocals设置为parent的inheritableThreadLocals
parent是什么?以前也说过了,就是建立这个线程的线程,也就是平时说的父线程
因此说
借助于inheritableThreadLocals,能够实现,建立线程向被建立线程数据传递
看下下面的方法
逻辑很清晰,建立了一个ThreadLocalMap
inheritableThreadLocals就是ThreadLocalMap类型的
简单理解:这个建立的ThreadLocalMap就是根据入参的ThreadLocalMap,拷贝建立一份
小结:
Thread对象,经过内部的
ThreadLocal.ThreadLocalMap inheritableThreadLocals = null;
维护从父线程(建立该线程的线程)继承而来的数据
原理就是在建立线程时,若是当前线程的inheritableThreadLocals不为null,那么将会复制一份保存在本身的ThreadLocal.ThreadLocalMap inheritableThreadLocals中
InheritableThreadLocal类解析
对比下 下面的两幅图片,上面为Thread中的相关方法
下图为InheritableThreadLocal中的三个方法
很显然,InheritableThreadLocal做为子类,重写了这几个方法
经过对getMap和createMap方法的重写,能够看得出来,只是内部操做的变量发生了变化,从threadLocals转换为inheritableThreadLocals
而对于childValue方法,还记得刚才的构造方法么(看注释called only by createInheritedMap)
也就是说在父线程建立子线程,初始化InheritableThreadLocal时会用到
总结
InheritableThreadLocal的核心概念仍旧是ThreadLocal.ThreadLocalMap以及ThreadLocal
InheritableThreadLocal是 ThreadLocal的子类
在Thread内部经过维护 ThreadLocal.ThreadLocalMap inheritableThreadLocals 进行父子线程数据的传递
而这个数据则是经过在建立Thread对象的时候,借助于内部的init方法,调用createInheritedMap方法,从父线程(当前建立线程)中复制的一份
后续的数据读取解析,则是经过inheritableThreadLocals变量,与内部的那个threadLocals没有什么关系
换个思路理解,他就是另一个ThreadLocal,假定Thread定义了两个“ThreadLocal“,其中一个在建立线程的时候会从父线程复制一份
只不过从实现上、以及逻辑上,他继承了ThreadLocal而已,而后覆盖了几个方法