0
  • 聊天消息
  • 系統(tǒng)消息
  • 評(píng)論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫(xiě)文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

ThreadLocal父子線程之間該如何傳遞數(shù)據(jù)?

jf_ro2CN3Fa ? 來(lái)源:芋道源碼 ? 2023-02-20 11:26 ? 次閱讀

來(lái)源:飛天小牛肉


每個(gè)線程都有自己的一個(gè) ThreadLocalMap,ThreadLocal 持有的數(shù)據(jù)就是存在這個(gè) Map 里的(Thread.ThreadLocalMap threadLocals),所以能夠?qū)崿F(xiàn)線程隔離,畢竟每個(gè)線程的 ThreadLocalMap 都是不一樣的

如果子線程想要拿到父線程的中的 ThreadLocal 值怎么辦呢 ?

比如會(huì)有以下的這種代碼的實(shí)現(xiàn)。在子線程中調(diào)用 get 時(shí),我們拿到的 Thread 對(duì)象是當(dāng)前子線程對(duì)象,對(duì)吧,每個(gè)線程都有自己獨(dú)立的 ThreadLocal,那么當(dāng)前子線程的 ThreadLocalMap 是 null 的(而父線程,也就是 main 線程中的 ThreadLocalMap 是有數(shù)據(jù)的),所以我們得到的 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);
}
}

結(jié)果輸出如下:

父線程的值:芋道源碼
子線程的值:null

要如何解決這個(gè)問(wèn)題呢?

我們先來(lái)從 Thread 類(lèi)中找找思路:

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

你會(huì)發(fā)現(xiàn),在 ThreadLocalMap threadLocals 的下方,還有一個(gè) ThreadLocalMap 變量 inherittableThreadLocals,inherit 翻譯為繼承

先看下這個(gè)變量的注釋?zhuān)?em style="color:rgb(14,136,235);letter-spacing:.3em;">InheritableThreadLocal values pertaining to this thread. This map is maintained by the InheritableThreadLocal class.

oho,這里出現(xiàn)了一個(gè)渣渣輝都從未體驗(yàn)過(guò)的傳新類(lèi):InheritableThreadLocal

翻譯一下注釋?zhuān)蟾啪褪牵绻闶褂?InheritableThreadLocal,那么保存的數(shù)據(jù)都已經(jīng)不在原來(lái)的 ThreadLocal.ThreadLocalMap threadLocals 里面了,而是在一個(gè)新的 ThreadLocal.ThreadLocalMap inheritableThreadLocals 變量中了。

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

所以,如果想讓上面那段代碼中,子線程能夠拿到父線程的 ThreadLocal 值,只需要把 ThreadLocal 聲明改為 InheritableThreadLocal 就可以了

下面我們具體來(lái)看下 InheritableThreadLocal 是怎么做到父子線程傳值的。

首先看下 new Thread 的時(shí)候線程都做了些什么 Thread#init()

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

if(inheritThreadLocals&&parent.inheritableThreadLocals!=null)
//copy父線程的map,創(chuàng)建一個(gè)新的map賦值給當(dāng)前線程的inheritableThreadLocals
this.inheritableThreadLocals=
ThreadLocal.createInheritedMap(parent.inheritableThreadLocals);

//省略部分代碼
}

核心其實(shí)就是上面幾句代碼,如果你設(shè)置了 inheritableThreadLocals 變量,那么 Thread 就會(huì)把父線程 ThreadLocal threadLocals 中的所有數(shù)據(jù)都 copy 到子線程的 InheritableThreadLocal inheritableThreadLocals 。

而且,copy 調(diào)用的 createInheritedMap 方法其實(shí)是一個(gè)淺拷貝函數(shù),key 和 value 都是原來(lái)的引用地址,這里所謂的 copy 其實(shí)就是把一個(gè) Map 中的數(shù)據(jù)復(fù)制到另一個(gè) Map 中:

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

至此,大致的解釋了 InheritableThreadLocal 為什么能解決父子線程傳遞 Threadlcoal 值的問(wèn)題了,總結(jié)下:

  1. 在創(chuàng)建 InheritableThreadLocal 對(duì)象的時(shí)候賦值給線程的 t.inheritableThreadLocals 變量
  2. 在創(chuàng)建新線程的時(shí)候會(huì) check 父線程中 t.inheritableThreadLocals 變量是否為 null,如果不為 null 則 copy 一份數(shù)據(jù)到子線程的 t.inheritableThreadLocals 成員變量中去
  3. InheritableThreadLocal 重寫(xiě)了 getMap(Thread) 方法,所以 get 的時(shí)候,就會(huì)從 t.inheritableThreadLocals 中拿到 ThreadLocalMap 對(duì)象,從而實(shí)現(xiàn)了可以拿到父線程 ThreadLocal 中的值

審核編輯 :李倩


聲明:本文內(nèi)容及配圖由入駐作者撰寫(xiě)或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場(chǎng)。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問(wèn)題,請(qǐng)聯(lián)系本站處理。 舉報(bào)投訴
  • 數(shù)據(jù)
    +關(guān)注

    關(guān)注

    8

    文章

    6715

    瀏覽量

    88316
  • 變量
    +關(guān)注

    關(guān)注

    0

    文章

    607

    瀏覽量

    28257
  • 線程
    +關(guān)注

    關(guān)注

    0

    文章

    501

    瀏覽量

    19580

原文標(biāo)題:ThreadLocal 父子線程之間該如何傳遞數(shù)據(jù)?

文章出處:【微信號(hào):芋道源碼,微信公眾號(hào):芋道源碼】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。

收藏 人收藏

    評(píng)論

    相關(guān)推薦

    ThreadLocal實(shí)例應(yīng)用

    。通常情況下,為了保證線程安全,我們需要使用鎖或其他同步機(jī)制。然而,有些情況下,我們希望在每個(gè)線程中都有一份獨(dú)立的數(shù)據(jù)副本,這就是ThreadLocal派上用場(chǎng)的地方。
    的頭像 發(fā)表于 09-30 10:19 ?587次閱讀
    <b class='flag-5'>ThreadLocal</b>實(shí)例應(yīng)用

    ThreadLocal的定義、用法及優(yōu)點(diǎn)

    ThreadLocal 簡(jiǎn)介 ThreadLocal是Java中一個(gè)非常重要的線程技術(shù)。它可以讓每個(gè)線程都擁有自己的變量副本,避免了線程間的
    的頭像 發(fā)表于 09-30 10:14 ?879次閱讀
    <b class='flag-5'>ThreadLocal</b>的定義、用法及優(yōu)點(diǎn)

    LabVIEW多線程編程數(shù)據(jù)傳遞教程

    很多時(shí)候在一個(gè)VI的不同線程或者不同VI的不同線程中需要有一些交互——這些線程并不能完全獨(dú)立運(yùn)行,需要一定的數(shù)據(jù)通信才能正確執(zhí)行,這時(shí)就需要在編程時(shí)使用LabVIEW提供的
    的頭像 發(fā)表于 11-24 10:05 ?5006次閱讀
    LabVIEW多<b class='flag-5'>線程</b>編程<b class='flag-5'>數(shù)據(jù)傳遞</b>教程

    鴻蒙原生應(yīng)用開(kāi)發(fā)-ArkTS語(yǔ)言基礎(chǔ)類(lèi)庫(kù)多線程TaskPool和Worker的對(duì)比(二)

    是基于消息傳遞的,Worker通過(guò)序列化機(jī)制與宿主線程之間相互通信,完成命令及數(shù)據(jù)交互。 本文參考引用HarmonyOS官方開(kāi)發(fā)文檔,基于API9。
    發(fā)表于 03-26 15:25

    線程程之線程間通訊

    線程程之線程間通訊七、線程間通訊  一般而言,應(yīng)用程序中的一個(gè)次要線程總是為主線程執(zhí)行特
    發(fā)表于 10-22 11:43

    Linux系統(tǒng)中進(jìn)程與線程之間的關(guān)系

    線程同步是指線程之間在相互通信時(shí)避免破壞各自數(shù)據(jù)的能力。同步問(wèn)題是由前面說(shuō)到的Win32系統(tǒng)的CPU時(shí)間片分配方式引起的。雖然在某一時(shí)刻,只有一個(gè)線程占用CPU(單CPU時(shí))時(shí)間,但是
    發(fā)表于 09-07 15:48

    請(qǐng)教一下線程之間通信問(wèn)題

    我想請(qǐng)教一下。兩個(gè)線程之間不需要進(jìn)行同步。只有一些狀態(tài)需要從A線程傳輸?shù)紹線程。如果說(shuō)數(shù)據(jù)只有一個(gè)字節(jié)的話,還有需要使用線程通信的那些函數(shù)去
    發(fā)表于 02-01 16:28

    QNX消息傳遞及其在線程間通信的應(yīng)用

    本文介紹了QNX 嵌入式實(shí)時(shí)多任務(wù)操作系統(tǒng)的消息傳遞和微內(nèi)核體系結(jié)構(gòu)的特點(diǎn),創(chuàng)建線程的方法,消息傳遞的基本原理,以及阻塞式消息傳遞線程間通
    發(fā)表于 08-11 08:46 ?31次下載

    Delphi教程之多線程數(shù)據(jù)庫(kù)

    Delphi教程之多線程數(shù)據(jù)庫(kù),很好的Delphi資料,快來(lái)下載學(xué)習(xí)吧。
    發(fā)表于 04-11 15:59 ?5次下載

    Python、線程和全局解釋器鎖

    線程有開(kāi)始,順序執(zhí)行和結(jié)束三部分。它有一個(gè)自己的指令指針,記錄自己運(yùn)行到什么地方。 線程的運(yùn)行可能被搶占(中斷),或暫時(shí)的被掛起(也叫睡眠),讓其它的線程運(yùn)行,這叫做讓步。 一個(gè)進(jìn)程中的各個(gè)
    的頭像 發(fā)表于 11-19 18:02 ?3456次閱讀

    ThreadLocal發(fā)生內(nèi)存泄漏的原因

    前言 ThreadLocal 的作用是提供線程內(nèi)的局部變量,這種變量在線程的生命周期內(nèi)起作用,減少同一個(gè)線程內(nèi)多個(gè)函數(shù)或者組件之間一些公共變
    的頭像 發(fā)表于 05-05 16:23 ?3605次閱讀

    ThreadLocal源碼解析及實(shí)戰(zhàn)應(yīng)用

    ThreadLocal 是一個(gè)關(guān)于創(chuàng)建線程局部變量的類(lèi)。
    的頭像 發(fā)表于 01-29 14:53 ?404次閱讀

    用這4招 優(yōu)雅的實(shí)現(xiàn)Spring Boot異步線程數(shù)據(jù)傳遞

    Spring Boot 自定義線程池實(shí)現(xiàn)異步開(kāi)發(fā)相信看過(guò)陳某的文章都了解,但是在實(shí)際開(kāi)發(fā)中需要在父子線程之間傳遞一些數(shù)據(jù),比如用戶(hù)信息,鏈路
    的頭像 發(fā)表于 01-30 10:40 ?1026次閱讀

    PyQT5+OpenCV多線程協(xié)作演示

    學(xué)習(xí)多線程最典型的問(wèn)題就是如何在多個(gè)線程之間傳遞消息與寫(xiě)作,PyQT5的線程支持在不同線程之間傳遞
    的頭像 發(fā)表于 03-08 14:58 ?1185次閱讀

    如何使用pthread_barrier_xxx系列函數(shù)來(lái)實(shí)現(xiàn)多線程之間的同步?

    在Linux系統(tǒng)中提供了多種同步機(jī)制,本文主要講講如何使用pthread_barrier_xxx系列函數(shù)來(lái)實(shí)現(xiàn)多線程之間進(jìn)行同步的方法。
    的頭像 發(fā)表于 10-23 14:43 ?771次閱讀
    如何使用pthread_barrier_xxx系列函數(shù)來(lái)實(shí)現(xiàn)多<b class='flag-5'>線程之間</b>的同步?