TransmittableThreadLocal详解(转)

1、简介

TransmittableThreadLocal 是Alibaba开源的、用于解决 “在使用线程池等会缓存线程的组件情况下传递ThreadLocal” 问题的 InheritableThreadLocal 扩展。若希望 TransmittableThreadLocal 在线程池与主线程间传递,需配合 TtlRunnableTtlCallable 使用。

2、使用场景

下面是几个典型场景例子。

  1. 分布式跟踪系统
  2. 应用容器或上层框架跨应用代码给下层SDK传递信息
  3. 日志收集记录系统上下文

3、源码分析

TransmittableThreadLocal 继承自 InheritableThreadLocal,这样可以在不破坏ThreadLocal 本身的情况下,使得当用户利用 new Thread() 创建线程时仍然可以达到传递InheritableThreadLocal 的目的。

public class TransmittableThreadLocal extends InheritableThreadLocal {}

TransmittableThreadLocal 相比较 InheritableThreadLocal 很关键的一点改进是引入holder变量,这样就不必对外暴露Thread中的 inheritableThreadLocals(参考InheritableThreadLocal详解),保持ThreadLocal.ThreadLocalMap的封装性。

  private static InheritableThreadLocal, ?>> holder =
            new InheritableThreadLocal, ?>>() {
                @Override
                protected Map, ?> initialValue() {
                    return new WeakHashMap, Object>();
                }

                @Override
                protected Map, ?> childValue(Map, ?> parentValue) {
                    return new WeakHashMap, Object>(parentValue);
                }
            };

个人认为 holder 变量的设计,极大体现了作者的智慧,让人无数次献上膝盖。。。


    @Override
    public final T get() {
        T value = super.get();
        if (null != value) {
            addValue();
        }
        return value;
    }

    @Override
    public final void set(T value) {
        super.set(value);
        if (null == value) { // may set null to remove value
            removeValue();
        } else {
            addValue();
        }
    }

    @Override
    public final void remove() {
        removeValue();
        super.remove();
    }
    private void addValue() {
       if (!holder.get().containsKey(this)) {
            holder.get().put(this, null); // WeakHashMap supports null value.
        }
    }

    private void removeValue() {
        holder.get().remove(this);
    }

4、工作流程简介

自定义 TtlRunnable 实现 Runnable,TtlRunnable初始化方法中保持当前线程中已有的TransmittableThreadLocal

private TtlRunnable(Runnable runnable, boolean releaseTtlValueReferenceAfterRun) {
    this.copiedRef = new AtomicReference, Object>>(TransmittableThreadLocal.copy());
    this.runnable = runnable;
    this.releaseTtlValueReferenceAfterRun = releaseTtlValueReferenceAfterRun;
}

线程池中线程 调用run方法,执行前先backup holder中所有的TransmittableThreadLocal, copiedRef中不存在,holder存在的,说明是后来加进去的,remove掉holder中的;将copied中的TransmittableThreadLocal set到当前线程中

public void run() {
    Map, Object> copied = copiedRef.get();
    if (copied == null || releaseTtlValueReferenceAfterRun && !copiedRef.compareAndSet(copied, null)) {
        throw new IllegalStateException("TTL value reference is released after run!");
    }

    Map, Object> backup = TransmittableThreadLocal.backupAndSetToCopied(copied);
    try {
        runnable.run();
    } finally {
        TransmittableThreadLocal.restoreBackup(backup);
    }
}

 

执行后再恢复 backup 的数据到 holder 中(backup中不存在,holder中存在的TransmittableThreadLocal,从holder中remove掉),将 backup 中的 TransmittableThreadLocal set到当前线程中


作者:沈渊
链接:https://www.jianshu.com/p/e0774f965aa3
來源:简书
简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处。

你可能感兴趣的:(架构)