searchusermenu
  • 发布文章
  • 消息中心
点赞
收藏
评论
分享
原创

TransmittableThreadLocal简介

2024-09-23 09:42:59
34
0

什么是 TransmittableThreadLocal?

TransmittableThreadLocal(TTL)是一种扩展自 ThreadLocal 的机制,它允许在不同线程或进程之间传递变量。这种机制特别适用于那些需要在线程之间共享数据的场景,如线程池、异步任务处理、微服务架构等。

TransmittableThreadLocal 的核心优势

1. 跨线程传递

传统的 ThreadLocal 变量只能在创建它的线程内部访问,而 TransmittableThreadLocal 可以跨越线程边界,将变量值从一个线程传递到另一个线程。

2. 跨进程传递

在分布式系统中,服务之间可能需要共享某些上下文信息。TransmittableThreadLocal 可以通过序列化和反序列化机制,实现跨进程的变量传递。

3. 减少内存泄漏风险

TransmittableThreadLocal 通常提供了更精细的控制机制,允许开发者在适当的时候清理变量,从而减少因线程复用导致的内存泄漏风险。

TransmittableThreadLocal 的工作原理

TransmittableThreadLocal 的工作原理主要依赖于它内部维护的一个 Map 结构,这个 MapThreadLocal 的值与线程ID关联起来。当任务从一个线程传递到另一个线程时,TransmittableThreadLocal 会将这些值一起传递过去。

1. 值的存储

当一个变量被存储到 TransmittableThreadLocal 中时,它会将变量的值与当前线程的ID关联起来。这样,每个线程都有一个独立的变量副本。

2. 值的传递

当任务从一个线程传递到另一个线程时,TransmittableThreadLocal 会将当前线程的 Map 中的值复制到目标线程的 Map 中。这样,目标线程就可以访问到源线程的变量值。

3. 值的清理

在任务执行完毕后,为了避免内存泄露,TransmittableThreadLocal 会清理目标线程中的变量副本。

使用 TransmittableThreadLocal

使用 TransmittableThreadLocal 通常需要以下几个步骤:

1. 创建 TransmittableThreadLocal 实例

首先,你需要创建一个 TransmittableThreadLocal 实例来存储你想要跨线程传递的变量。

TransmittableThreadLocal<String> context = new TransmittableThreadLocal<>();

2. 设置变量值

在任务开始之前,设置 TransmittableThreadLocal 的值。

context.set("some value");

3. 跨线程传递

将任务提交到线程池或其他并发执行机制中。TransmittableThreadLocal 会负责在线程之间传递变量值。

ExecutorService executorService = Executors.newFixedThreadPool(10);
executorService.submit(() -> {
    String value = context.get();
    // 使用 value 进行后续处理
});

4. 清理变量

在任务执行完毕后,清理 TransmittableThreadLocal 的值,以避免内存泄漏。

context.remove();

TransmittableThreadLocal 在实际应用中的例子

1. 微服务架构中的上下文传递

在微服务架构中,一个请求可能需要经过多个服务处理。使用 TransmittableThreadLocal 可以确保请求的上下文信息(如用户身份、会话信息等)在服务之间传递。

2. 异步任务处理

在处理异步任务时,TransmittableThreadLocal 可以确保任务的上下文信息在不同的线程中保持一致。

3. 线程池中的资源共享

在线程池中,TransmittableThreadLocal 可以用于共享那些不适合在多个线程间共享的资源,如数据库连接、文件句柄等。

TransmittableThreadLocal 实现日志全链路追踪

在并发及异步条件下,不同线程之间的线程变量无法共享,普通的手段难以实现对请求id进行全链路的日志追踪,虽然可以通过重写线程池的提交方法来强行实现线程变量的共享,但是这样扩展性不好,后续不好维护,此时可以结合 TransmittableThreadLocal 来实现线程池内共享主线程变量,来实现全链路日志追踪的效果。

1. 创建定制的 TransmittableThreadLocal 实例

此工具类中引入 TransmittableThreadLocal 实例,重写其中的 beforeExecuteafterExecuteinitialValue 方法。

TransmittableThreadLocal<Map<String, String>> ttlMDC = new TransmittableThreadLocal<Map<String, String>>() {
    /**
     * 在多线程数据传递的时候,将数据复制一份给MDC
     */
    @Override
    protected void beforeExecute() {
        final Map<String, String> mdc = get();
        mdc.forEach(MDC::put);
    }

    @Override
    protected void afterExecute() {
        MDC.clear();
    }

    @Override
    protected Map<String, String> initialValue() {
        return Maps.newHashMap();
    }
};

1. 创建线程池并用 TtlExecutors 包装

创建线程池并使用 TtlExecutors 进行包装,后续使用此线程池即可实现线程池内同步主线程的 Slf4j 日志信息。

ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
// 使用ttl进行包装
return TtlExecutors.getTtlExecutorService(executor.getThreadPoolExecutor());

结论

TransmittableThreadLocal 提供了一种强大的机制,使得线程局部变量可以在不同线程甚至不同进程之间传递。这在构建复杂的并发应用程序,特别是在微服务和分布式系统中,是一个非常有用的特性。通过合理使用 TransmittableThreadLocal,开发者可以更加灵活地管理线程间的变量传递,提高应用程序的性能和可靠性。

0条评论
作者已关闭评论
k****n
6文章数
0粉丝数
k****n
6 文章 | 0 粉丝
k****n
6文章数
0粉丝数
k****n
6 文章 | 0 粉丝
原创

TransmittableThreadLocal简介

2024-09-23 09:42:59
34
0

什么是 TransmittableThreadLocal?

TransmittableThreadLocal(TTL)是一种扩展自 ThreadLocal 的机制,它允许在不同线程或进程之间传递变量。这种机制特别适用于那些需要在线程之间共享数据的场景,如线程池、异步任务处理、微服务架构等。

TransmittableThreadLocal 的核心优势

1. 跨线程传递

传统的 ThreadLocal 变量只能在创建它的线程内部访问,而 TransmittableThreadLocal 可以跨越线程边界,将变量值从一个线程传递到另一个线程。

2. 跨进程传递

在分布式系统中,服务之间可能需要共享某些上下文信息。TransmittableThreadLocal 可以通过序列化和反序列化机制,实现跨进程的变量传递。

3. 减少内存泄漏风险

TransmittableThreadLocal 通常提供了更精细的控制机制,允许开发者在适当的时候清理变量,从而减少因线程复用导致的内存泄漏风险。

TransmittableThreadLocal 的工作原理

TransmittableThreadLocal 的工作原理主要依赖于它内部维护的一个 Map 结构,这个 MapThreadLocal 的值与线程ID关联起来。当任务从一个线程传递到另一个线程时,TransmittableThreadLocal 会将这些值一起传递过去。

1. 值的存储

当一个变量被存储到 TransmittableThreadLocal 中时,它会将变量的值与当前线程的ID关联起来。这样,每个线程都有一个独立的变量副本。

2. 值的传递

当任务从一个线程传递到另一个线程时,TransmittableThreadLocal 会将当前线程的 Map 中的值复制到目标线程的 Map 中。这样,目标线程就可以访问到源线程的变量值。

3. 值的清理

在任务执行完毕后,为了避免内存泄露,TransmittableThreadLocal 会清理目标线程中的变量副本。

使用 TransmittableThreadLocal

使用 TransmittableThreadLocal 通常需要以下几个步骤:

1. 创建 TransmittableThreadLocal 实例

首先,你需要创建一个 TransmittableThreadLocal 实例来存储你想要跨线程传递的变量。

TransmittableThreadLocal<String> context = new TransmittableThreadLocal<>();

2. 设置变量值

在任务开始之前,设置 TransmittableThreadLocal 的值。

context.set("some value");

3. 跨线程传递

将任务提交到线程池或其他并发执行机制中。TransmittableThreadLocal 会负责在线程之间传递变量值。

ExecutorService executorService = Executors.newFixedThreadPool(10);
executorService.submit(() -> {
    String value = context.get();
    // 使用 value 进行后续处理
});

4. 清理变量

在任务执行完毕后,清理 TransmittableThreadLocal 的值,以避免内存泄漏。

context.remove();

TransmittableThreadLocal 在实际应用中的例子

1. 微服务架构中的上下文传递

在微服务架构中,一个请求可能需要经过多个服务处理。使用 TransmittableThreadLocal 可以确保请求的上下文信息(如用户身份、会话信息等)在服务之间传递。

2. 异步任务处理

在处理异步任务时,TransmittableThreadLocal 可以确保任务的上下文信息在不同的线程中保持一致。

3. 线程池中的资源共享

在线程池中,TransmittableThreadLocal 可以用于共享那些不适合在多个线程间共享的资源,如数据库连接、文件句柄等。

TransmittableThreadLocal 实现日志全链路追踪

在并发及异步条件下,不同线程之间的线程变量无法共享,普通的手段难以实现对请求id进行全链路的日志追踪,虽然可以通过重写线程池的提交方法来强行实现线程变量的共享,但是这样扩展性不好,后续不好维护,此时可以结合 TransmittableThreadLocal 来实现线程池内共享主线程变量,来实现全链路日志追踪的效果。

1. 创建定制的 TransmittableThreadLocal 实例

此工具类中引入 TransmittableThreadLocal 实例,重写其中的 beforeExecuteafterExecuteinitialValue 方法。

TransmittableThreadLocal<Map<String, String>> ttlMDC = new TransmittableThreadLocal<Map<String, String>>() {
    /**
     * 在多线程数据传递的时候,将数据复制一份给MDC
     */
    @Override
    protected void beforeExecute() {
        final Map<String, String> mdc = get();
        mdc.forEach(MDC::put);
    }

    @Override
    protected void afterExecute() {
        MDC.clear();
    }

    @Override
    protected Map<String, String> initialValue() {
        return Maps.newHashMap();
    }
};

1. 创建线程池并用 TtlExecutors 包装

创建线程池并使用 TtlExecutors 进行包装,后续使用此线程池即可实现线程池内同步主线程的 Slf4j 日志信息。

ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
// 使用ttl进行包装
return TtlExecutors.getTtlExecutorService(executor.getThreadPoolExecutor());

结论

TransmittableThreadLocal 提供了一种强大的机制,使得线程局部变量可以在不同线程甚至不同进程之间传递。这在构建复杂的并发应用程序,特别是在微服务和分布式系统中,是一个非常有用的特性。通过合理使用 TransmittableThreadLocal,开发者可以更加灵活地管理线程间的变量传递,提高应用程序的性能和可靠性。

文章来自个人专栏
多线程同步
1 文章 | 1 订阅
0条评论
作者已关闭评论
作者已关闭评论
0
0