ThreadLocal、InheritableThreadLocal與TransmittableThreadLocal深度解析

文章目錄

    • 一、概念說明
      • 1、ThreadLocal
      • 2、InheritableThreadLocal
      • 3、TransmittableThreadLocal
    • 二、使用場景
      • 1、ThreadLocal
      • 2、InheritableThreadLocal
      • 3、TransmittableThreadLocal
    • 三、存在的問題
      • 1、ThreadLocal
      • 2、InheritableThreadLocal
      • 3、TransmittableThreadLocal
    • 四、示例代碼
      • 1、ThreadLocal 示例
      • 2、InheritableThreadLocal 示例
      • 3、TransmittableThreadLocal 示例
    • 五、特性對比
    • 六、選型建議
    • 七、最佳實踐
    • 八、總結

一、概念說明

1、ThreadLocal

ThreadLocal是一個用于創建線程局部變量的類。每個線程都有自己獨立的變量副本,線程之間互不影響。

2、InheritableThreadLocal

InheritableThreadLocalThreadLocal的子類,允許子線程繼承父線程的局部變量副本。適用于需要在子線程中使用父線程變量的場景。

3、TransmittableThreadLocal

TransmittableThreadLocal是一個阿里巴巴開源的庫(java-concurrent)提供的類,它不僅支持父子線程之間的變量傳遞,還支持在異步任務中傳遞變量。它的設計目的是解決在多線程環境中,尤其是在使用線程池和異步編程時,線程上下文信息傳遞的問題。

二、使用場景

1、ThreadLocal

  • 數據庫連接管理:在高并發應用中,每個線程可以持有自己的數據庫連接,避免了連接競爭和線程安全問題。這樣做可以提高數據庫操作的效率。

  • 用戶會話管理:在Web應用中,可以使用ThreadLocal來存儲每個用戶的會話信息,例如用戶ID、權限等,以便在整個請求處理過程中使用。

  • 日志上下文:在多線程環境中,可以使用ThreadLocal來存儲與當前線程相關的日志信息,如請求ID、用戶信息等,方便在日志中追蹤請求的來源。

  • 配置管理:在某些應用中,根據不同的線程上下文需要加載不同的配置參數,可以使用ThreadLocal來存儲這些配置信息。

  • 表單驗證:在處理表單提交時,可以將表單驗證狀態保存在ThreadLocal中,以便在不同的驗證步驟中共享狀態。

2、InheritableThreadLocal

  • 任務上下文傳遞:在使用線程池或異步框架時,父線程的上下文信息(如用戶認證信息)可以通過InheritableThreadLocal傳遞給子線程,方便子線程進行相應的操作。

  • 事務管理:在分布式事務中,可以使用InheritableThreadLocal將事務上下文傳遞給子線程,確保在異步操作中可以正確地參與事務。

  • 安全上下文:在Web應用中,可以使用InheritableThreadLocal來存儲用戶的安全上下文信息(如角色、權限等),以便在異步處理時能夠繼承這些信息。

  • 配置傳遞:在復雜的任務執行鏈中,使用InheritableThreadLocal可以將父線程的配置參數傳遞給子線程,確保子線程能夠正確地使用這些配置。

3、TransmittableThreadLocal

  • 異步任務處理:在使用ForkJoinPool或CompletableFuture等異步框架時,可以使用TransmittableThreadLocal來傳遞上下文信息,確保異步任務能夠訪問到父線程的狀態。

  • 微服務調用鏈:在微服務架構中,使用TransmittableThreadLocal可以在不同服務之間傳遞調用鏈信息(如Trace ID),方便進行分布式追蹤和監控。

  • 消息隊列消費:在消息隊列的消費場景中,使用TransmittableThreadLocal可以將消息處理的上下文信息傳遞給異步處理的消費者,確保消費者能夠獲取到必要的信息。

  • 定時任務:在定時任務的執行過程中,使用TransmittableThreadLocal可以將上下文信息傳遞給每一個執行的線程,確保任務能夠在異步執行時保持一致性。

  • 環境變量傳遞:在多線程環境中,使用TransmittableThreadLocal可以在不同的線程中共享一些環境變量(如配置文件路徑、系統環境變量等),確保各個線程都能夠訪問到相同的信息。

三、存在的問題

1、ThreadLocal

  • 內存泄漏:在使用線程池時,線程會被重復利用。當線程不再使用時,如果沒有顯式調用remove()方法清除ThreadLocal中存儲的值,可能導致內存泄漏。因為線程池中的線程在被重用時,可能會保留之前線程的上下文信息,導致不一致的狀態。

  • 線程不安全:如果多個線程使用同一個ThreadLocal實例,可能引發數據不一致。尤其在高并發的情況下,錯誤的使用可能導致共享數據的競爭條件。

2、InheritableThreadLocal

  • 性能開銷:當使用InheritableThreadLocal時,父線程的數據會被復制到子線程,這在大量線程創建時可能導致性能開銷,尤其是在高并發環境下。

  • 上下文混淆:在使用線程池時,子線程可能會繼承不必要的父線程上下文,導致數據混淆。例如,如果父線程的上下文在執行期間發生了變化,子線程可能會得到不一致的狀態。

3、TransmittableThreadLocal

  • 復雜性與依賴性:雖然TransmittableThreadLocal能夠解決異步任務中的上下文傳遞問題,但它依賴于第三方庫,增加了項目的復雜性。開發者需要學習和理解這個庫的使用方法。

  • 狀態一致性問題:在異步處理的場景中,如果父線程的狀態在傳遞過程中發生變化,可能導致子線程獲取到的狀態不一致。這在高并發場景中容易出現問題。

四、示例代碼

1、ThreadLocal 示例

特性:每個線程都有自己獨立的threadLocalValue副本。主線程設置的值不會影響子線程。

public class ThreadLocalExample {private static ThreadLocal<Integer> threadLocalValue = ThreadLocal.withInitial(() -> 0);public static void main(String[] args) {threadLocalValue.set(10);System.out.println("Main Thread Value: " + threadLocalValue.get());new Thread(() -> {threadLocalValue.set(20);System.out.println("Child Thread Value: " + threadLocalValue.get());}).start();new Thread(() -> {System.out.println("Another Child Thread Value: " + threadLocalValue.get());}).start();}
}

2、InheritableThreadLocal 示例

特性:子線程可以繼承父線程的inheritableThreadLocalValue值。主線程設置的值可以被繼承,且子線程可以修改自己的值。

public class InheritableThreadLocalExample {private static InheritableThreadLocal<Integer> inheritableThreadLocalValue = InheritableThreadLocal.withInitial(() -> 0);public static void main(String[] args) {inheritableThreadLocalValue.set(10);System.out.println("Main Thread Value: " + inheritableThreadLocalValue.get());new Thread(() -> {System.out.println("Child Thread Inherited Value: " + inheritableThreadLocalValue.get());inheritableThreadLocalValue.set(20);System.out.println("Child Thread New Value: " + inheritableThreadLocalValue.get());}).start();new Thread(() -> {System.out.println("Another Child Thread Inherited Value: " + inheritableThreadLocalValue.get());}).start();}
}

3、TransmittableThreadLocal 示例

特性TransmittableThreadLocal允許在異步任務中傳遞父線程的值。即使在不同的線程執行時,父線程的值仍然可以被訪問。

注意:使用此示例需要導入maven依賴,另外請根據需要使用最新版本)

<dependency><groupId>com.alibaba</groupId><artifactId>transmittable-thread-local</artifactId><version>2.0.4</version> 
</dependency>
public class TransmittableThreadLocalExample {private static TransmittableThreadLocal<String> transmittableThreadLocalValue = new TransmittableThreadLocal<>();public static void main(String[] args) {transmittableThreadLocalValue.set("Hello from Main Thread");ExecutorService executorService = Executors.newFixedThreadPool(2);executorService.submit(() -> {System.out.println("First Thread Transmittable Value: " + transmittableThreadLocalValue.get());});executorService.submit(() -> {System.out.println("Second Thread Transmittable Value: " + transmittableThreadLocalValue.get());});executorService.shutdown();try {executorService.awaitTermination(1, TimeUnit.SECONDS);} catch (InterruptedException e) {Thread.currentThread().interrupt();}}
}

五、特性對比

特性ThreadLocalInheritableThreadLocalTransmittableThreadLocal
線程隔離??????
父子線程繼承?????
線程池支持????
內存泄漏風險
性能開銷較高
使用復雜度簡單中等復雜

六、選型建議

  1. 選擇ThreadLocal

    • 當你需要在每個線程中存儲獨立的變量,并且不需要在子線程中訪問這些變量時,使用ThreadLocal。但在使用線程池時,務必在每次任務執行結束后調用remove()來清理數據,以防止內存泄漏。
  2. 選擇InheritableThreadLocal

    • 當你需要在父線程和子線程之間共享一些變量時,使用InheritableThreadLocal。要注意在使用線程池時,可能會導致上下文信息混淆,確保上下文信息的管理是清晰的。
  3. 選擇TransmittableThreadLocal

    • 當你的應用程序涉及異步任務或線程池,并且需要在不同的線程間傳遞上下文信息時,使用TransmittableThreadLocal。在使用時,需謹慎對待狀態一致性的問題,確保傳遞的數據在異步場景中不會被意外修改。

七、最佳實踐

  • 清理資源:在使用ThreadLocalInheritableThreadLocal時,應在不再使用時調用remove()方法,以防止內存泄漏。

  • 避免濫用:不要過度使用ThreadLocal,特別是在高并發環境中。確保它只在必要時使用,以免增加復雜性。

  • 性能測試:在使用InheritableThreadLocalTransmittableThreadLocal時,進行性能測試,以確保它們不會成為應用程序的瓶頸。

  • 文檔說明:在代碼中清晰地記錄使用ThreadLocalInheritableThreadLocalTransmittableThreadLocal的原因和預期效果,以便于后續維護。

八、總結

在Java中,ThreadLocalInheritableThreadLocalTransmittableThreadLocal分別用于不同的線程局部變量管理場景。雖然它們在多線程編程中非常有用,但也需要注意潛在的內存泄漏和數據一致性問題,特別是在與線程池結合使用時。在使用這些類時,應根據具體的業務需求選擇合適的實現方式,并注意清理不再使用的線程局部變量,以避免不必要的內存占用。

通過合理使用這些工具,并遵循最佳實踐,可以有效提升多線程環境下的數據管理能力,減少潛在的錯誤和內存泄漏風險,從而增強系統的穩定性和性能。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/86911.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/86911.shtml
英文地址,請注明出處:http://en.pswp.cn/web/86911.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

ERP系統Bug記錄

2025.06.30 2025/06/30-10:51:02 [http-nio-9999-exec-3] com.yxx.jsh.erp.service.LogService - 異常碼[300],異常提示[數據查詢異常],異常[{}] java.lang.NullPointerException: nullat com.yxx.jsh.erp.base.TableSupport.getBuildPageRequest(TableSupport.java:46)at com…

C# Avalonia 的 Source Generators 用處

C# Avalonia 的 Source Generators 用處 文章目錄 **1. 自動生成 MVVM 綁定代碼****2. 強類型 XAML 數據綁定****3. 自動注冊視圖&#xff08;View&#xff09;與視圖模型&#xff08;ViewModel&#xff09;****4. 資源文件與本地化的強類型訪問****5. 路由事件與命令的自動化處…

stm32之測量占空比

#include "tim4.h"void TIM4_Init(void) {// 開啟時鐘RCC->APB1ENR | RCC_APB1ENR_TIM4EN;RCC->APB2ENR | RCC_APB2ENR_IOPBEN; // 使用 TIM4 的 GPIOB 時鐘// 配置 PB6 為浮空輸入 CNF 01 MODE 00GPIOB->CRL & ~GPIO_CRL_MODE6;GPIOB->CRL & ~G…

工廠模式 - Flutter中的UI組件工廠,按需生產各種“產品

想要動態創建不同風格的按鈕&#xff1f;想一鍵切換整個主題&#xff1f;工廠模式就是你的"生產流水線"&#xff01; 想象一下這個場景&#xff1a; 你決定擴大奶茶店業務&#xff0c;推出兩個品牌系列&#xff1a; 經典系列&#xff1a;傳統珍珠奶茶&#xff0c;紅…

基于 SpringBoot+Vue.js+ElementUI 的 Cosplay 論壇設計與實現7000字論文

基于 SpringBootVue.jsElementUI 的 Cosplay 論壇設計與實現 摘要 本論文設計并實現了一個基于 SpringBoot、Vue.js 和 ElementUI 的 Cosplay 論壇平臺。該平臺旨在為 Cosplay 愛好者提供一個集作品展示、交流互動、活動組織于一體的綜合性社區。論文首先分析了 Cosplay 論壇…

超標量處理器11-Alpha21264 處理器

1. 簡介 21264處理器是一款4-way&#xff0c;亂序執行的超標量處理器&#xff0c;采用0.35um的CMOS工藝&#xff0c;工作電壓是2.2V, 工作頻率是466-667MHz; 處理器能支持60條指令&#xff0c;也即ROB的深度是60; Load/Store指令也采取亂序執行, 總共7級流水。I-CACHE和D-CACH…

Spring 中 Bean 的生命周期

一、什么是 Bean 生命周期&#xff1f; Spring 中的 Bean 生命周期是指一個 Bean 從 被容器創建到 最終銷毀 所經歷的一系列過程。 它體現了 Spring IOC 容器在管理 Bean 實例時所執行的各個鉤子流程&#xff0c;包括初始化、依賴注入、增強處理、銷毀等多個環節。 二、Bean 生…

C++ 中 std::string 與 QString 的深度剖析

在 C 編程領域&#xff0c;std::string 和 QString 是兩種廣泛應用的字符串類型&#xff0c;它們在設計理念、功能特性以及適用場景上都呈現出鮮明的特點。本文將從多個維度對這兩種字符串類型進行深度剖析&#xff0c;并詳細闡述它們之間的相互轉化方法。 std::string 是 C 標…

不止于“修補”:我如何用Adobe AI重塑設計與視頻敘事流程

最近我深度體驗了一把來自英國Parvis School of Economics and Music的Adobe正版教育訂閱&#xff0c;在把玩PhotoShop、Premiere Pro這些“老伙計”的新功能時&#xff0c;的確挖到了一些寶藏&#xff0c;覺得非常有必要與大家說道說道。首先得聊聊這個訂閱給我的直觀感受&…

重頭開始學ROS(5)---阿克曼底盤的URDF建模與Gazebo控制(使用Xacro優化)

阿克曼底盤的URDF建模與Gazebo控制&#xff08;使用Xacro優化&#xff09; 阿克曼底盤建模 建模 我們使用后輪驅動&#xff0c;前輪轉向的阿克曼底盤模型。 那么對于后輪只需進行正常的continous joint連接即可 對于前輪&#xff0c;有兩個自由度&#xff0c;旋轉和轉向&…

RabbitMq中啟用NIO

? 所屬類 com.rabbitmq.client.ConnectionFactory&#x1f9e0; 使用背景 RabbitMQ Java 客戶端默認使用傳統的 阻塞 I/O (java.net.Socket) 實現。如果你希望&#xff1a; 更好地控制 線程數獲得更好的 并發性能降低 每個連接的線程占用在高并發連接或消費者數量較多的系統…

[Dify]-基礎篇2- 如何注冊并快速上手 Dify 平臺

在生成式 AI 應用開發新時代,如何快速搭建一個高效、可維護、易上線的 AI 工具,是每位開發者關注的核心。Dify,正是為此而生的一站式平臺。本篇將以新手視角,帶你從注冊賬號、配置環境,到構建應用、部署上線,手把手完成你的第一個 AI 項目。 注冊并設置工作環境 1. 賬號…

Java面試寶典:基礎七

153. 如何實現對象克隆? 答: 對象克隆有兩種主要方式: 淺克隆:實現Cloneable接口并重寫Object.clone() class Person implements Cloneable {String name;Car car; // 引用類型@Override

spring-security原理與應用系列:requestMatchers和authorizeRequests

目錄 簡單示例 WebSecurityConfig requestMatchers ???????requestMatchers ???????antMatchers ???????chainRequestMatchers ???????setMatchers ???????requestMatcher ???????WebSecurity ???????performBuild…

Bessel位勢方程求解步驟

問題 考慮偏微分方程&#xff08;PDE&#xff09;&#xff1a; ? Δ u u f , x ∈ R n , -\Delta u u f, \quad x \in \mathbb{R}^n, ?Δuuf,x∈Rn, 其中 f ∈ L 2 ( R n ) f \in L^2(\mathbb{R}^n) f∈L2(Rn)。這是一個線性橢圓型方程&#xff0c;稱為 Bessel 位勢方…

if __name__ == ‘__main__‘:

基本概念 if __name__ __main__: 是一個條件判斷語句&#xff0c;用于確定當前模塊是作為主程序運行&#xff0c;還是被其他模塊導入。 __name__ 變量 __name__ 是Python的一個內置變量&#xff0c;表示當前模塊的名稱當一個模塊被直接運行時&#xff0c;__name__ 的值會被…

淺談Apache HttpClient的相關配置和使用

Apache HttpClient是由Apache軟件基金會維護的一款開源HTTP客戶端庫&#xff0c;對比最基礎的 HttpURLConnection 而言,它的優勢時支持連接池管理&#xff0c;攔截器&#xff08;Interceptor&#xff09;機制&#xff0c;同步/異步請求支持等能力。 在使用這個組件時&#xff…

【Teensy】在ArduinoIDE中配置Teensy4.1

1.文件——首選項 在其他開發板管理器地址這里添加&#xff1a; https://www.pjrc.com/teensy/package_teensy_index.json 點擊確定&#xff01; 2.安裝Teensy(for Arduino IDE…) 按照圖中1&#xff0c;2&#xff0c;3操作&#xff01;可以選擇上一個版本&#xff08;不使用最…

企業自建云概念解讀|私有云、專有云、混合云、分布式云、企業云

隨著云計算技術逐漸成熟&#xff0c;越來越多的企業開始在本地數據中心自行搭建云平臺&#xff0c;滿足數據合規、業務性能與連續性、節約成本等多方面的需求。不過&#xff0c;面對多種多樣的自建云產品&#xff0c;不少用戶會有類似的疑問&#xff1a;自建云等于私有云嗎&…

反彈 Shell 升級為全交互終端的兩種高效方法

目錄 ?? 升級反彈 Shell 為全交互終端:兩種高效方法 ??? 方法 1:利用 Python pty.spawn 創建偽終端 ?? 操作步驟