Java并发编程: TransmittableThreadLocal实现父子线程之间值传递_transmittablethreadlocal父子线程数据传递-程序员宅基地

技术标签: java  【Java并发编程】  

一、TransmittableThreadLocal概念

1、介绍

TransmittableThreadLocal 是 Alibaba 开源框架 transmittable-thread-local 中的一个核心类,它扩展了 Java 的标准 ThreadLocal 类。与标准的 ThreadLocal 不同,TransmittableThreadLocal 的值可以在线程之间传递,尤其是在线程池中的线程复用场景下。

2、主要特性:

  • 线程间传递:TransmittableThreadLocal 的值可以在线程之间传递,这在某些场景中是非常有用的,例如在使用线程池时,任务之间的数据传递。
  • 避免内存泄漏:像标准的 ThreadLocal 一样,TransmittableThreadLocal 也需要注意避免内存泄漏。确保在不再需要值时调用 remove() 方法来清除数据。
  • 集成与扩展:TransmittableThreadLocal 提供了与标准 ThreadLocal 的良好集成,使得迁移和使用更加简单。同时,它也提供了一些扩展功能,以满足更复杂的需求。

3、使用场景:

  • 线程池中的上下文传递:当使用线程池时,线程可能会被多个任务复用。使用 TransmittableThreadLocal,可以在任务之间传递上下文信息,而无需显式地在线程之间传递参数。
    • 链路追踪:如日志链路追踪,例如:traceId在线程池中的传递。
    • 用户会话信息:在http请求中获取用户id和租户id信息。
  • 跨组件的数据传递:在复杂的分布式系统或微服务架构中,有时需要在不同的组件或模块之间传递数据。虽然这通常通过其他机制(如消息头、HTTP 上下文等)实现,但在某些情况下,使用 TransmittableThreadLocal 可能是一种简单且有效的方法。

4、注意事项:

  • 内存泄漏:与 ThreadLocal 一样,需要小心处理 TransmittableThreadLocal 的生命周期,以避免内存泄漏。
  • 线程安全:虽然 TransmittableThreadLocal 本身提供了线程间的数据传递功能,但存储在其中的数据本身仍然需要是线程安全的。
  • 集成与兼容性:虽然 TransmittableThreadLocal 与标准的 ThreadLocal 兼容,但在某些复杂的场景下,可能需要额外的考虑和测试来确保其正常工作。

总的来说,TransmittableThreadLocal 是一个强大的工具,用于在线程之间传递数据,特别是在使用线程池等高级并发场景时。然而,使用它时需要谨慎,并确保正确处理其生命周期和线程安全性。

二、TransmittableThreadLocal的使用

1、TransmittableThreadLocal使用的2种方式

  • 使用TtlRunnable get(@Nullable Runnable runnable)装饰Runnable或使用TtlCallable get(@Nullable Callable callable)装饰callable
  • ExecutorService getTtlExecutorService(@Nullable ExecutorService executorService)装饰executorService

2、在线程池中的应用

线程之间的值传递验证:
引入依赖:

        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>transmittable-thread-local</artifactId>
            <version>2.14.4</version>
        </dependency>

使用方式一:

package chatpter08;

import com.alibaba.ttl.TransmittableThreadLocal;
import com.alibaba.ttl.TtlRunnable;
import com.alibaba.ttl.threadpool.TtlExecutors;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

public class TestTransmittableThreadLocal02 {
    
    public static void main(String[] args) throws InterruptedException {
    
        final TransmittableThreadLocal transmittableThreadLocal = new TransmittableThreadLocal();
        transmittableThreadLocal.set("aaa");
        Runnable runnable = () -> {
    
            try {
    
                TimeUnit.MILLISECONDS.sleep(100);
            } catch (InterruptedException e) {
    
                throw new RuntimeException(e);
            }
            System.out.println("====" + Thread.currentThread().getId() + "====");
            System.out.println(transmittableThreadLocal.get());
        };

        ExecutorService executorService = Executors.newFixedThreadPool(1);

        int i = 0;
        while(Boolean.TRUE) {
    
            executorService.execute(TtlRunnable.get(runnable));
            transmittableThreadLocal.set(i + "AA");
            i ++;
        }
    }
}

使用方式二:

package chatpter08;

import com.alibaba.ttl.TransmittableThreadLocal;
import com.alibaba.ttl.threadpool.TtlExecutors;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

public class TestTransmittableThreadLocal {
    
    public static void main(String[] args) throws InterruptedException {
    
        final TransmittableThreadLocal transmittableThreadLocal = new TransmittableThreadLocal();
        transmittableThreadLocal.set("aaa");
        Runnable runnable = () -> {
    
            try {
    
                TimeUnit.MILLISECONDS.sleep(100);
            } catch (InterruptedException e) {
    
                throw new RuntimeException(e);
            }
            System.out.println("====" + Thread.currentThread().getId() + "====");
            System.out.println(transmittableThreadLocal.get());
        };

        ExecutorService executorService = Executors.newFixedThreadPool(1);
        ExecutorService ttlExecutorService = TtlExecutors.getTtlExecutorService(executorService);

        int i = 0;
        while(Boolean.TRUE) {
    
            ttlExecutorService.execute(runnable);
            transmittableThreadLocal.set(i + "AA");
            i ++;
        }
    }
}

运行结果:

====13====
aaa
====13====
0AA
====13====
1AA
====13====
2AA
====13====
3AA
====13====
4AA
====13====
5AA
====13====
6AA
====13====
7AA
====13====
8AA

通过运行结果可以看到TransmittableThreadLocal具有在在线程之间值传递的功能

三、TransmittableThreadLocal原理

在设计上采用了装饰器模型来增强Runnable和Callable等线程任务。

四、应用场景

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/yuming226/article/details/137377546

智能推荐

Thread和Runnable-程序员宅基地

文章浏览阅读222次,点赞3次,收藏9次。两者都创建线程的方式,不同之处在于前者是类,后者是接口。使用的时候重写他们即可。

什么是寄存器-程序员宅基地

文章浏览阅读753次,点赞2次,收藏2次。寄存器是计算机中的一种短时存储器,通常用于存储临时数据和指令。它的速度比内存要快得多,因为它直接位于 CPU 内部。寄存器通常很小,只能存储几个字节的数据。..._寄存器是什么

JavaScript学习(六)—location对象常用的属性和方法_location对象的属性-程序员宅基地

文章浏览阅读5k次,点赞13次,收藏11次。location对象常用的属性一、location对象作用:location是window对象的一个属性,本身也是对象类型,它的作用是用来获取文档对象的相关信息,如文档的URL地址信息。二、location对象常用的属性:1)href属性作用:获取或设置窗口中的url地址信息获取格式:window.location.href更改的格式:window.location.href=新的地址信息;注意:在使用href属性修改url地址薪资时会产生浏览记录事例:点击按钮,跳转到百度页面<b_location对象的属性

负的CPU保护环-程序员宅基地

文章浏览阅读438次。什么是CPU保护环?在计算机科学中,分级保护域(英语:hierarchical protection domains),经常被叫作保护环(Protection Rings),又称环型保护(Rings Protection)、CPU环(CPU Rings),简称Rings。这是一种用来在发生故障时保护数据和功能,提升容错度,避免恶意操作 ,提升计算机安全的设计方式。工作在不同Ring..._cpu环

各式各样的极品程序员_顶级程序员玩算法, google csdn-程序员宅基地

文章浏览阅读728次。---转自CSDN, http://www.csdn.net/article/2013-12-24/2817904-The-Taxonomy-of-Terrible-Programmers本文作者Aaron是MarkedUp创始人兼.Net开发者。在这篇文章里,作者根据自己平时在工作中的所见所闻,列举了几个比较有代表性的极品程序员类型。他们各有自己的特点和性格,在软件开发工作中,这种特_顶级程序员玩算法, google csdn

数字图像处理:视觉概述_数字图像处理简述人的视觉-程序员宅基地

文章浏览阅读667次。常见的媒体常见的媒体有声音、文字、图形、图像、动画、视频。其中文字、图形、图像、动画、视频都和视觉相关,所以视觉非常重要。什么是视觉?视觉是光刺激作用于视觉器官而产生的主观映像,人眼是视觉系统的外周感受器。视觉器官主要包括眼睛、视觉通道(视神经等)和视中枢(大脑的枕叶皮层)。从解剖的角度看眼睛最外:角膜和巩膜中间:脉络膜最内:视网膜从功能的角度看眼睛屈光系统:角膜、房水、晶状体、玻璃体构成感光系统:视网膜人"看见"物体的过程物体(发射或反射)的光线,经人眼的屈光媒质(角膜_数字图像处理简述人的视觉

随便推点

EasyUi 权限-程序员宅基地

文章浏览阅读71次。权限目的:是为了让不同的用户可以操作系统中不同资源直接点说就是不同的用户可以看到左侧不同的菜单实现思路:① 菜单不同的原因在于,利用不同menuid进行查询,原本默认查询的是所有菜单,是通过-1去查的;② menuid由来:是登录用户id查询中间表数据所得来的③ 权限设计(用户权限多对多)代码:基于上节课的基础(工具类和jar包)登录页面:login.jsp<%@ pag...

nodejs安装失败_nodejs setup wizard ended-程序员宅基地

文章浏览阅读2.8k次。本来是将nodejs安装在一个移动硬盘里,但是移动硬盘被我格式化了,所有没有正确的卸载nodejs,导致现在再安装一个nodejs会提示失败。即使通过控制面板卸载程序也是报了一个node.js setup wizard ended prematurely的错误误打误撞,发现可以通过编辑以下注册表值来尝试HKEY_LOCAL_MACHINE\SOFTWARE\Node.js在那里,您将找到一个InstallPath属性。将驱动器重命名为有效驱动器,然后再次尝试安装节点。还要从PATH变量中删除_nodejs setup wizard ended

jar包下载到本地maven库,_scala-parser-combinators_2.11-1.0.4.jar坐标-程序员宅基地

文章浏览阅读188次。本地jar包maven引用_scala-parser-combinators_2.11-1.0.4.jar坐标

DBGridEh大全_dbgrideh 分页-程序员宅基地

文章浏览阅读1.6w次。查看完全版本:dbgrid应用全书论坛跳转到...╋名狐堂├名狐介绍├名狐讲座╋技术论坛├VFP 论坛├DELPHI├CGI、ASP、JAVA论坛├LINUX 论坛├dot NET论坛├其它语言C,C++,PB,VB╋专题技术├VFP + SQL Server├类的应用、VFP调用API├企业管理与软件╋情感论坛├情感_dbgrideh 分页

过采样与欠采样&图像重采样(上采样&下采样)_欠采样和过采样原理-程序员宅基地

文章浏览阅读1.9w次,点赞16次,收藏88次。参考文章:https://blog.csdn.net/majinlei121/article/details/46742339https://blog.csdn.net/Chaolei3/article/details/80225756https://blog.csdn.net/h763247747/article/details/100135924https://blog.csdn.ne..._欠采样和过采样原理

苹果计算机的优势,苹果笔记本的优缺点详细分析-程序员宅基地

文章浏览阅读1.8w次。苹果笔记本可以说是目前最轻薄性能的电脑品牌了,虽然苹果笔记本的款式和型号有很多很多,但是苹果笔记本的优缺点基本上是大致一样的,想了解吗?下面随着小编一起来了解下吧!一、苹果笔记本的优点1、苹果笔记本外观精致漂亮华丽、设计外形简洁紧凑,美观大方、独特、清丽、高贵、经典。品牌响亮。2、硬件主板芯片采用intel芯片组,兼容windows系统,稳定性与兼容性保证。苹果笔记本可以选择MAC OS和WIND..._苹果笔记本电脑优缺点

推荐文章

热门文章

相关标签