Java多线程 - InheritableThreadLocal类原理简介使用和父子线程传递数据详解

1.测试代码

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则能够获取到值

image_5c77364a_7c3

结论:

在子线程中,可以获取到父线程的InheritableThreadLocal类型变量的值,而不能获取到ThreadLocal类型变量的值

对于ThreadLocal我们已经有了详尽的分析,在Thread中有一个map,以ThreadLocal类型的变量作为key

在子线程中,get方法自然是获取子线程中的map,很显然,子线程中的map并没有设置任何值,所以初始值null被读取出来

但是,InheritableThreadLocal为什么能够读取出来?

2. 原理分析

在Thread类中,有一个ThreadLocal.ThreadLocalMap类型的变量:inheritableThreadLocals,他的类型同Thread内部的threadLocals变量

image_5c77364a_13aa

在Thread的init方法中,有一段初始化设置(应该还记得,这个init方法是所有的Thread对象创建的必经之路) 

下面为部分代码片段拼接

image_5c77364a_2ad4

从上面的这个方法可以很清晰的看得到 

如果parent的inheritableThreadLocals不是null,那么就会将当前线程的inheritableThreadLocals设置为parent的inheritableThreadLocals

parent是什么?之前也说过了,就是创建这个线程的线程,也就是平时说的父线程 

所以说 

借助于inheritableThreadLocals,可以实现,创建线程向被创建线程数据传递

看下下面的方法 

逻辑很清晰,创建了一个ThreadLocalMap 

inheritableThreadLocals就是ThreadLocalMap类型的 

简单理解:这个创建的ThreadLocalMap就是根据入参的ThreadLocalMap,拷贝创建一份

 

image_5c77364a_68

小结:

Thread对象,通过内部的 

    ThreadLocal.ThreadLocalMap inheritableThreadLocals = null; 

维护从父线程(创建该线程的线程)继承而来的数据 

原理就是在创建线程时,如果当前线程的inheritableThreadLocals不为null,那么将会复制一份保存在自己的ThreadLocal.ThreadLocalMap inheritableThreadLocals中

3. InheritableThreadLocal类解析

image_5c77364a_7073

image_5c77364b_73a8

通过对getMap和createMap方法的重写,可以看得出来,只是内部操作的变量发生了变化,从threadLocals转换为inheritableThreadLocals

而对于childValue方法,还记得刚才的构造方法么(看注释called only by createInheritedMap) 

也就是说在父线程创建子线程,初始化InheritableThreadLocal时会用到

image_5c77364b_45a1

4. 总结

InheritableThreadLocal的核心概念仍旧是ThreadLocal.ThreadLocalMap以及ThreadLocal 

InheritableThreadLocal是 ThreadLocal的子类 

在Thread内部通过维护    ThreadLocal.ThreadLocalMap inheritableThreadLocals 进行父子线程数据的传递 

而这个数据则是通过在创建Thread对象的时候,借助于内部的init方法,调用createInheritedMap方法,从父线程(当前创建线程)中复制的一份 

后续的数据读取解析,则是通过inheritableThreadLocals变量,与内部的那个threadLocals没有什么关系 

换个思路理解,他就是另外一个ThreadLocal,假定Thread定义了两个“ThreadLocal“,其中一个在创建线程的时候会从父线程复制一份 

只不过从实现上、以及逻辑上,他继承了ThreadLocal而已,然后覆盖了几个方法

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值