业务场景实战(七)阿里TTL线程池

思维导图

思维导图.png

系列总目录

  • 业务场景实战汇总

背景

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

  1. 透传上下文信息,run方法调用结束时自动restore上下文信息
  2. 线程池使用CallerRunsPolicy时,避免了手动回收上下文信息会将主线程的上下文信息清空

使用

    // 使用TransmittableThreadLocal
    static TransmittableThreadLocal transmittableThreadLocal = new TransmittableThreadLocal<>();


    public static void main(String[] args) throws InterruptedException {

        ExecutorService executorService = Executors.newFixedThreadPool(1);
        // 用TtlExecutors装饰线程池
        executorService = TtlExecutors.getTtlExecutorService(executorService); 

        transmittableThreadLocal.set("i am a transmittable parent");
        executorService.execute((Runnable) () -> {

            System.out.println(transmittableThreadLocal.get());
            // 子线程设置新的值
            transmittableThreadLocal.set("i am a old transmittable parent");

        });
        System.out.println(transmittableThreadLocal.get());

        TimeUnit.SECONDS.sleep(1);
        // 主线程设置新的值
        transmittableThreadLocal.set("i am a new transmittable parent");
        executorService.execute((Runnable) () -> System.out.println(transmittableThreadLocal.get()));
    }


    i am a transmittable parent 
    i am a transmittable parent
    i am a new transmittable parent
  • 执行代码后发现,使用TTL和TtlExecutors.getTtlExecutorService(executorService)装饰线程池之后,在每次调用任务的时,都会将当前的主线程的TTL数据copy到子线程里面,执行完成后,再清除掉。同时子线程里面的修改回到主线程时其实并没有生效。这样可以保证每次任务执行的时候都是互不干涉的

源码

  • 完整时序图


    完整时序图
  1. 线程池执行时,执行了 ExecutorTtlWrapper execute 方法,execute 方法中调用了 4.1.1,4.1.1 方法中创建了一个 TtlRunnable 对象返回了。
    TtlRunnable 构造方法中,调用了 TransmittableThreadLocal.Transmitter.capture() 获取当前线程中所有的上下文,并储存在 AtomicReference 中。
  2. 当线程执行时,调用 TtlRunnable run 方法,TtlRunnable 会从 AtomicReference 中获取出调用线程中所有的上下文,并把上下文给 TransmittableThreadLocal.Transmitter.replay 方法把上下文复制到当前线程。并把上下文备份。
  3. 当线程执行完,调用 TransmittableThreadLocal.Transmitter.restore 并把备份的上下文传入,恢复备份的上下文,把后面新增的上下文删除,并重新把上下文复制到当前线程。

参考文章

  • Java 多线程上下文传递在复杂场景下的实践
  • TransmittableThreadLocal 源码解析

你可能感兴趣的:(业务场景实战(七)阿里TTL线程池)