上一篇文章中对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而已,然后覆盖了几个方法
 

InheritableThreadLocal类原理简介使用 父子线程传递数据详解 多线程中篇(十八)的更多相关文章

  1. Java线程创建形式 Thread构造详解 多线程中篇(五)

    Thread作为线程的抽象,Thread的实例用于描述线程,对线程的操纵,就是对Thread实例对象的管理与控制. 创建一个线程这个问题,也就转换为如何构造一个正确的Thread对象. 构造方法列表 ...

  2. 线程组ThreadGroup分析详解 多线程中篇(三)

    线程组,顾名思义,就是线程的组,逻辑类似项目组,用于管理项目成员,线程组就是用来管理线程. 每个线程都会有一个线程组,如果没有设置将会有些默认的初始化设置 而在java中线程组则是使用类ThreadG ...

  3. Thread类详解 多线程中篇(二)

    Java.lang.Thread是Java应用程序员对Java多线程的第一站,Thread就是对Java线程本身的抽象 所以在Java中的线程编程概念中,一个Thread实例 == 一个线程 线程有哪 ...

  4. ThreadLocal父子线程传递实现方案

    介绍InheritableThreadLocal之前,假设对 ThreadLocal 已经有了一定的理解,比如基本概念,原理,如果没有,可以参考:ThreadLocal源码分析解密.在讲解之前我们先列 ...

  5. Java多线程初学者指南(7):向线程传递数据的三种方法

    在传统的同步开发模式下,当我们调用一个函数时,通过这个函数的参数将数据传入,并通过这个函数的返回值来返回最终的计算结果.但在多线程的异步开发模式下,数据的传递和返回和同步开发模式有很大的区别.由于线程 ...

  6. 深入解析ThreadLocal 详解、实现原理、使用场景方法以及内存泄漏防范 多线程中篇(十七)

    简介 从名称看,ThreadLocal 也就是thread和local的组合,也就是一个thread有一个local的变量副本 ThreadLocal提供了线程的本地副本,也就是说每个线程将会拥有一个 ...

  7. Android事件传递机制详解及最新源码分析——ViewGroup篇

    版权声明:本文出自汪磊的博客,转载请务必注明出处. 在上一篇<Android事件传递机制详解及最新源码分析--View篇>中,详细讲解了View事件的传递机制,没掌握或者掌握不扎实的小伙伴 ...

  8. Android 的事件传递机制,详解

    Android 的事件传递机制,详解 前两天和一个朋友聊天的时候.然后说到事件传递机制.然后让我说的时候,忽然发现说的不是非常清楚,事实上Android 的事件传递机制也是知道一些,可是感觉自己知道的 ...

  9. Android Touch事件传递机制详解 下

    尊重原创:http://blog.csdn.net/yuanzeyao/article/details/38025165 资源下载:http://download.csdn.net/detail/yu ...

随机推荐

  1. BZOJ_3629_[JLOI2014]聪明的燕姿_dfs

    BZOJ_3629_[JLOI2014]聪明的燕姿_dfs Description 阴天傍晚车窗外 未来有一个人在等待 向左向右向前看 爱要拐几个弯才来 我遇见谁会有怎样的对白 我等的人他在多远的未来 ...

  2. BZOJ_4269_再见Xor_线性基

    BZOJ_4269_再见Xor_线性基 Description 给定N个数,你可以在这些数中任意选一些数出来,每个数可以选任意多次,试求出你能选出的数的异或和的最大值和严格次大值. Input 第一行 ...

  3. java 日期类 小结

    import java.text.*; import java.util.*; class Test2 { public static void main(String[] args) { Syste ...

  4. 【Maven篇】---解决Maven线上部署java.lang.ClassNotFoundException和no main manifest attribute解决方法

    一.前述 maven 线上部署的话会出现一些问题比如java.lang.ClassNotFoundException或者no main manifest attribute的话,是因为maven 配置 ...

  5. 【重学计算机】操作系统D3章:存储管理

    1. 存储管理的基本概念 逻辑地址:用户地址,从零开始编号 一维逻辑地址:(地址) 二维逻辑地址:(段号: 段内地址) 主存储器的复用方式 按分区:主存划分为多个固定/可变分区,一个程序占一个分区 按 ...

  6. Android6.0 源码修改之 仿IOS添加全屏可拖拽浮窗返回按钮

    前言 之前写过屏蔽系统导航栏功能的文章,具体可看Android6.0 源码修改之屏蔽导航栏虚拟按键(Home和RecentAPP)/动态显示和隐藏NavigationBar 在某些特殊定制的版本中要求 ...

  7. navicate for mysql之-Can't connect to MySQL server on 'localhost'(10038)

    1. 卸载navicate for mysql 会留下很多坑,主要是卸载不干净,卸载之后重新安装会出现之前的库内容和库链接还存在的问题,这种情况的出现是卸载残余. 解决办法,清理注册表(网上很多教程但 ...

  8. Window10 输入法不能删除问题解决

    有时候我们想删除一个输入法,却发现输入法Remove 按钮是Disalbe 的,这时可以使用下面方法回避这个问题. 1.使用 Administrator 运行 Windows powerSheell. ...

  9. ASP.NET Core 中断请求了解一下(翻译)

    ASP.NET Core知多少系列:总体介绍及目录 本文所讲方式仅适用于托管在Kestrel Server中的应用.如果托管在IIS和IIS Express上时,ASP.NET Core Module ...

  10. webgl自学笔记——深度监测与混合

    这一章中关于webgl中颜色的使用我们将深入研究.我们将从研究颜色在webgl和essl中如何被组装和获取开始.然后我们讨论在物体.光照和场景中颜色的使用.这之后我们将看到当一个物体在另一个物体前面是 ...