0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

ThreadLocal父子线程之间该如何传递数据?

jf_ro2CN3Fa 来源:芋道源码 2023-02-20 11:26 次阅读

来源:飞天小牛肉


每个线程都有自己的一个 ThreadLocalMap,ThreadLocal 持有的数据就是存在这个 Map 里的(Thread.ThreadLocalMap threadLocals),所以能够实现线程隔离,毕竟每个线程的 ThreadLocalMap 都是不一样的

如果子线程想要拿到父线程的中的 ThreadLocal 值怎么办呢

比如会有以下的这种代码的实现。在子线程中调用 get 时,我们拿到的 Thread 对象是当前子线程对象,对吧,每个线程都有自己独立的 ThreadLocal,那么当前子线程的 ThreadLocalMap 是 null 的(而父线程,也就是 main 线程中的 ThreadLocalMap 是有数据的),所以我们得到的 value 也是 null

publicclassThreadLocalTest{
privatestaticThreadLocalthreadLocal=newThreadLocal();

publicstaticvoidmain(String[]args)throwsException{
threadLocal.set("芋道源码");
System.out.println("父线程的值:"+threadLocal.get());
newThread(newRunnable(){
@Override
publicvoidrun(){
System.out.println("子线程的值:"+threadLocal.get());
}
}).start();

Thread.sleep(2000);
}
}

结果输出如下:

父线程的值:芋道源码
子线程的值:null

要如何解决这个问题呢?

我们先来从 Thread 类中找找思路:

3e9401ae-b0c9-11ed-bfe3-dac502259ad0.png

你会发现,在 ThreadLocalMap threadLocals 的下方,还有一个 ThreadLocalMap 变量 inherittableThreadLocals,inherit 翻译为继承

先看下这个变量的注释:InheritableThreadLocal values pertaining to this thread. This map is maintained by the InheritableThreadLocal class.

oho,这里出现了一个渣渣辉都从未体验过的传新类:InheritableThreadLocal

翻译一下注释,大概就是,如果你使用 InheritableThreadLocal,那么保存的数据都已经不在原来的 ThreadLocal.ThreadLocalMap threadLocals 里面了,而是在一个新的 ThreadLocal.ThreadLocalMap inheritableThreadLocals 变量中了。

3ee74aee-b0c9-11ed-bfe3-dac502259ad0.png

所以,如果想让上面那段代码中,子线程能够拿到父线程的 ThreadLocal 值,只需要把 ThreadLocal 声明改为 InheritableThreadLocal 就可以了

下面我们具体来看下 InheritableThreadLocal 是怎么做到父子线程传值的。

首先看下 new Thread 的时候线程都做了些什么 Thread#init()

privatevoidinit(ThreadGroupg,Runnabletarget,Stringname,longstackSize,AccessControlContextacc){
//省略部分代码
Threadparent=currentThread();

if(inheritThreadLocals&&parent.inheritableThreadLocals!=null)
//copy父线程的map,创建一个新的map赋值给当前线程的inheritableThreadLocals
this.inheritableThreadLocals=
ThreadLocal.createInheritedMap(parent.inheritableThreadLocals);

//省略部分代码
}

核心其实就是上面几句代码,如果你设置了 inheritableThreadLocals 变量,那么 Thread 就会把父线程 ThreadLocal threadLocals 中的所有数据都 copy 到子线程的 InheritableThreadLocal inheritableThreadLocals

而且,copy 调用的 createInheritedMap 方法其实是一个浅拷贝函数,key 和 value 都是原来的引用地址,这里所谓的 copy 其实就是把一个 Map 中的数据复制到另一个 Map 中:

3f069656-b0c9-11ed-bfe3-dac502259ad0.png

至此,大致的解释了 InheritableThreadLocal 为什么能解决父子线程传递 Threadlcoal 值的问题了,总结下:

  1. 在创建 InheritableThreadLocal 对象的时候赋值给线程的 t.inheritableThreadLocals 变量
  2. 在创建新线程的时候会 check 父线程中 t.inheritableThreadLocals 变量是否为 null,如果不为 null 则 copy 一份数据到子线程的 t.inheritableThreadLocals 成员变量中去
  3. InheritableThreadLocal 重写了 getMap(Thread) 方法,所以 get 的时候,就会从 t.inheritableThreadLocals 中拿到 ThreadLocalMap 对象,从而实现了可以拿到父线程 ThreadLocal 中的值

审核编辑 :李倩


声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 数据
    +关注

    关注

    8

    文章

    7030

    浏览量

    89036
  • 变量
    +关注

    关注

    0

    文章

    613

    浏览量

    28370
  • 线程
    +关注

    关注

    0

    文章

    504

    浏览量

    19684

原文标题:ThreadLocal 父子线程之间该如何传递数据?

文章出处:【微信号:芋道源码,微信公众号:芋道源码】欢迎添加关注!文章转载请注明出处。

收藏 人收藏

    评论

    相关推荐

    ThreadLocal实例应用

    。通常情况下,为了保证线程安全,我们需要使用锁或其他同步机制。然而,有些情况下,我们希望在每个线程中都有一份独立的数据副本,这就是ThreadLocal派上用场的地方。
    的头像 发表于 09-30 10:19 672次阅读
    <b class='flag-5'>ThreadLocal</b>实例应用

    ThreadLocal的定义、用法及优点

    ThreadLocal 简介 ThreadLocal是Java中一个非常重要的线程技术。它可以让每个线程都拥有自己的变量副本,避免了线程间的
    的头像 发表于 09-30 10:14 1066次阅读
    <b class='flag-5'>ThreadLocal</b>的定义、用法及优点

    LabVIEW多线程编程数据传递教程

    很多时候在一个VI的不同线程或者不同VI的不同线程中需要有一些交互——这些线程并不能完全独立运行,需要一定的数据通信才能正确执行,这时就需要在编程时使用LabVIEW提供的
    的头像 发表于 11-24 10:05 6914次阅读
    LabVIEW多<b class='flag-5'>线程</b>编程<b class='flag-5'>数据传递</b>教程

    鸿蒙原生应用开发-ArkTS语言基础类库多线程TaskPool和Worker的对比(二)

    是基于消息传递的,Worker通过序列化机制与宿主线程之间相互通信,完成命令及数据交互。 本文参考引用HarmonyOS官方开发文档,基于API9。
    发表于 03-26 15:25

    线程程之线程间通讯

    线程程之线程间通讯七、线程间通讯  一般而言,应用程序中的一个次要线程总是为主线程执行特
    发表于 10-22 11:43

    Linux系统中进程与线程之间的关系

    线程同步是指线程之间在相互通信时避免破坏各自数据的能力。同步问题是由前面说到的Win32系统的CPU时间片分配方式引起的。虽然在某一时刻,只有一个线程占用CPU(单CPU时)时间,但是
    发表于 09-07 15:48

    请教一下线程之间通信问题

    我想请教一下。两个线程之间不需要进行同步。只有一些状态需要从A线程传输到B线程。如果说数据只有一个字节的话,还有需要使用线程通信的那些函数去
    发表于 02-01 16:28

    QNX消息传递及其在线程间通信的应用

    本文介绍了QNX 嵌入式实时多任务操作系统的消息传递和微内核体系结构的特点,创建线程的方法,消息传递的基本原理,以及阻塞式消息传递线程间通
    发表于 08-11 08:46 31次下载

    Delphi教程之多线程数据

    Delphi教程之多线程数据库,很好的Delphi资料,快来下载学习吧。
    发表于 04-11 15:59 5次下载

    Python、线程和全局解释器锁

    线程有开始,顺序执行和结束三部分。它有一个自己的指令指针,记录自己运行到什么地方。 线程的运行可能被抢占(中断),或暂时的被挂起(也叫睡眠),让其它的线程运行,这叫做让步。 一个进程中的各个线
    的头像 发表于 11-19 18:02 3518次阅读

    ThreadLocal发生内存泄漏的原因

    前言 ThreadLocal 的作用是提供线程内的局部变量,这种变量在线程的生命周期内起作用,减少同一个线程内多个函数或者组件之间一些公共变
    的头像 发表于 05-05 16:23 3681次阅读

    ThreadLocal源码解析及实战应用

    ThreadLocal 是一个关于创建线程局部变量的类。
    的头像 发表于 01-29 14:53 473次阅读

    用这4招 优雅的实现Spring Boot异步线程数据传递

    Spring Boot 自定义线程池实现异步开发相信看过陈某的文章都了解,但是在实际开发中需要在父子线程之间传递一些数据,比如用户信息,链路
    的头像 发表于 01-30 10:40 1137次阅读

    PyQT5+OpenCV多线程协作演示

    学习多线程最典型的问题就是如何在多个线程之间传递消息与写作,PyQT5的线程支持在不同线程之间传递
    的头像 发表于 03-08 14:58 1340次阅读

    如何使用pthread_barrier_xxx系列函数来实现多线程之间的同步?

    在Linux系统中提供了多种同步机制,本文主要讲讲如何使用pthread_barrier_xxx系列函数来实现多线程之间进行同步的方法。
    的头像 发表于 10-23 14:43 1058次阅读
    如何使用pthread_barrier_xxx系列函数来实现多<b class='flag-5'>线程之间</b>的同步?