TransmittableThreadLocal 解决了哪些问题?

Posted Dream_it_possible!

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了TransmittableThreadLocal 解决了哪些问题?相关的知识,希望对你有一定的参考价值。

目录

一、TransmittableThreadLocal使用场景

二、使用InheritableThreadLocal传递上下文存在的问题

三、TransmittableThreadLocal 解决了哪些问题?

四、如何使用TransmittableThreadLocal?

参考文献


随着现在应用的分布式以及各种中间件的使用,我们的系统也越来越多的功能和组件涉及到上下文,上下文问题实际上是一个易错的架构问题,因此我们需要统一对业务透明的解决方案。

一、TransmittableThreadLocal使用场景

        在使用线程池等会池化复用线程的执行组件情况下,transmittable-thread-local提供ThreadLocal值的传递功能,解决异步执行时上下文传递的问题 

        1. 分布式跟踪系统或全链路压测。

        2. 日志系统上下文。

        3. Session级cache。

        4. 应用容器或上层框架应用给下层SDK传递信息。

二、使用InheritableThreadLocal传递上下文存在的问题

        1) 每次传递完需要remove操作,如果忘记remove,会出现内存泄漏问题。

        2) 传递的时候不小心多remove了一次,那么会出现上下文丢失的问题。

        3) InheritableThreadLocal是在父线程创建的时候,将变量复制给子线程,这种方式虽然子线程能继承得到父线程的变量值,但是一般情况下,我们会在多线程环境下使用线程池,线程池会复用之前创建过的线程,不会每用一个线程就创建一个,也就是说这种情况下,子线程可能会得到之前父线程的变量值。

三、TransmittableThreadLocal 解决了哪些问题?

        1) 透明且自动完成所有异步执行上下文的捕捉与传递。

        2)  ttl通过对父线程所在的环境进行拷贝,子线程相当于是继承了父线程的上下文环境, 因此能够与父线程保持一致,ttl解决了InheritableThreadLocal传递变量给子线程出现混乱的问题。

四、如何使用TransmittableThreadLocal?

        我们可以通过maven直接添加TTL依赖

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

使用TransmittableThreadLocal设置变量:

private static TransmittableThreadLocal<Integer> requestIdTransmittableTheadLocal
                         = new TransmittableThreadLocal<>();

在给子线程传递变量时用ttl线程池和TransmittablThreadLocal:

private static Executor controlExectutors =         
TtlExecutors.getTtlExecutorService(Executors.newFixedThreadPool(5));

案例演示: 

package com.example.future;

import com.alibaba.ttl.TransmittableThreadLocal;
import com.alibaba.ttl.threadpool.TtlExecutors;
import com.example.future.util.ThreadPoolUtil;
import com.example.future.util.threadpolicy.DiscardOldestPolicy;
import com.google.common.util.concurrent.ThreadFactoryBuilder;

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.*;

/**
 * @decription:
 * @author: zhengbing.zhang
 * @date: 2021/7/6 15:01
 */
public class TransmittableThreadLocalDemo {

    private static TimeUnit keepAliveTimeUnit = TimeUnit.MINUTES;

    private static ExecutorService tomcatExecutors = new ThreadPoolExecutor(8, 16,
            60L, keepAliveTimeUnit, new LinkedBlockingDeque<>(100));

    //    private static ExecutorService controlExecutors = new ThreadPoolExecutor(8, 16,
//            60L, keepAliveTimeUnit, new LinkedBlockingDeque<>(100));
    // 使用ttl线程池
    private static Executor controlExectutors = TtlExecutors.getTtlExecutorService(Executors.newFixedThreadPool(5));

    private static TransmittableThreadLocal<Integer> requestIdTransmittableTheadLocal = new TransmittableThreadLocal<>();


    public static void main(String[] args) {

        for (int i = 0; i < 10; i++) {
            tomcatExecutors.submit(new ControlTask(i));
        }

        tomcatExecutors.shutdown();
    }

    static class ControlTask implements Runnable {

        private int i;

        public ControlTask(int i) {
            this.i = i;
        }

        @Override
        public void run() {
            requestIdTransmittableTheadLocal.set(i);
            System.out.println(Thread.currentThread().getName() + ":" + i);
            // ttl线程池只有execute()方法
            controlExectutors.execute(new BusinessTask(Thread.currentThread().getName()));
        }
    }

    static class BusinessTask implements Runnable {
        private String parentThreadName;

        public BusinessTask(String parentThreadName) {
            this.parentThreadName = parentThreadName;
        }



        @Override
        public void run() {
            System.out.println("parentThreadName:" + parentThreadName + ",id: " + requestIdTransmittableTheadLocal.get());
        }
    }


}

打印结果:

父线程与子线程的变量副本一致 !

参考文献

https://codechina.csdn.net/mirrors/alibaba/transmittable-thread-local

https://blog.csdn.net/qq_40378034/article/details/115272581

以上是关于TransmittableThreadLocal 解决了哪些问题?的主要内容,如果未能解决你的问题,请参考以下文章

阿里开源TransmittableThreadLocal(TTL)l的使用及原理解析

TransmittableThreadLocal相关组件实用解读,及如何达到线程池中的线程复用,及使用在哪些线程数据传递场景?

每日一博 - ThreadLocal VS InheritableThreadLocal VS TransmittableThreadLocal

TransmittableThreadLocal解决线程池本地变量问题,原来我一直理解错了

TransmittableThreadLocal解决线程池本地变量问题,原来我一直理解错了

我居然被TransmittableThreadLocal框架作者评论了