TransmittableThreadLocal

TransmittableThreadLocal

一、概述

1、背景

大多数系统会使用线程池技术,这已经不仅仅是InheritableThreadLocal能够解决的了。

TransmittableThreadLocal 是Alibaba开源,用于实现 在使用线程池等 会缓存线程的组件时 传递ThreadLocal

2、使用场景

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

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

3、maven依赖

<!-- TransmittableThreadLocal -->
<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>transmittable-thread-local</artifactId>
    <version>2.14.2</version>
</dependency>

4、生效前提

当我们使用线程池时,要使得线程池的变量传递起效果,需要:

  1. 使用TtlRunnable.get(runnable)Runnable进行包装

    使用TtlCallable.get(callable)Callable进行包装

  2. 使用TtlExecutors.getTtlExecutorExecutor进行包装

    使用TtlExecutors.getTtlExecutorServiceExecutorService进行包装

    使用TtlExecutors.getTtlScheduledExecutorServiceScheduledExecutorService进行包装

第二种方式其实就是在 executesubmit 时通过 TtlRunnableTtlCallable 对原任务进行包装

至于为什么要这样,可以在下面的源码分析中找到答案。

二、源码分析 - TransmittableThreadLocal

TransmittableThreadLocal 继承自 InheritableThreadLocal

public class TransmittableThreadLocal<T> extends InheritableThreadLocal<T> implements TtlCopier<T> {
    
}

使得当用户利用 new Thread() 创建线程时仍然可以达到传递InheritableThreadLocal 的目的。

1、构造方法

// com.alibaba.ttl.TransmittableThreadLocal

public TransmittableThreadLocal() {
    this(false);
}

public TransmittableThreadLocal(boolean disableIgnoreNullValueSemantics) {
    // 是否忽略null值set,默认false
    this.disableIgnoreNullValueSemantics = disableIgnoreNullValueSemantics;
}

2、holder

TransmittableThreadLocal 相比较 InheritableThreadLocal 很关键的一点改进是引入了holder变量

这样就不必对外暴露 Thread 中的 inheritableThreadLocals,保持 ThreadLocal.ThreadLocalMap 的封装性。

// com.alibaba.ttl.TransmittableThreadLocal

// holder其实就是InheritableThreadLocal的一个匿名内部类
private static final InheritableThreadLocal<WeakHashMap<TransmittableThreadLocal<Object>, ?>> holder =
    new InheritableThreadLocal<WeakHashMap<TransmittableThreadLocal<Object>, ?>>() {

    @Override
    protected WeakHashMap<TransmittableThreadLocal<Object>, ?> initialValue() {
        return new WeakHashMap<>();
    }

    @Override
    protected WeakHashMap<TransmittableThreadLocal<Object>, ?> childValue(
        WeakHashMap<TransmittableThreadLocal<Object>, ?> parentValue
    ) {
        return new WeakHashMap<>(parentValue);
    }
};
  • holder其实就是InheritableThreadLocal的一个匿名内部类。
  • holderfinal static 修饰。
  • holder 存储的是 WeakHashMap,key 是 TransmittableThreadLocal<Object>对象,value 是对应的值
    • WeakHashMapkeyWeakReference弱引用,方便回收

3、set 方法

// com.alibaba.ttl.TransmittableThreadLocal

// 调用 set() 方法时,同时处理 holder 中 this 指针
@Override
public final void set(T value) {
    if (!disableIgnoreNullValueSemantics && value == null) {
        // 不忽略null写入,则移除本地线程变量
        remove();
    } else {
        // 调用父类ThreadLocal的set方法
        super.set(value);
        // 添加到 holder 中
        addThisToHolder();
    }
}

private void addThisToHolder() {
    if (!holder.get().containsKey(this)) {
        // WeakHashMap supports null value.
        holder.get().put((TransmittableThreadLocal<Object>) this, null);
    }
}

4、remove 方法

// com.alibaba.ttl.TransmittableThreadLocal

// 调用 remove() 方法时,同时remove holder 中 this 指针
@Override
public final void remove() {
    // 从 holder 中移除
    removeThisFromHolder();
    // 调用父类ThreadLocal的remove方法
    super.remove();
}

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

5、get 方法

// com.alibaba.ttl.TransmittableThreadLocal


// 调用 get() 方法时,同时将 this 指针放入 holder
@Override
public final T get() {
    // 调用父类ThreadLocal的get方法
    T value = super.get();
    // 如果允许忽略null,或者value不为null,再次添加到holder
    if (disableIgnoreNullValueSemantics || value != null) 
        addThisToHolder();
    return value;
}

private void addThisToHolder() {
    if (!holder.get().containsKey(this)) {
        // WeakHashMap supports null value.
        holder.get().put((TransmittableThreadLocal<Object>) this, null);
    }
}

三、源码分析 - TtlExecutors

public final class TtlExecutors {

    public static Executor getTtlExecutor(@Nullable Executor executor) {
        if (TtlAgent.isTtlAgentLoaded() || executor == null || executor instanceof TtlEnhanced) {
            return executor;
        }
        // 包装Executor
        return new ExecutorTtlWrapper(executor, true);
    }

    public static ExecutorService getTtlExecutorService(@Nullable ExecutorService executorService) {
        if (TtlAgent.isTtlAgentLoaded() || executorService == null || executorService instanceof TtlEnhanced) {
            return executorService;
        }
        // 包装ExecutorService
        return new ExecutorServiceTtlWrapper(executorService, true);
    }
    
    public static ScheduledExecutorService getTtlScheduledExecutorService(@Nullable ScheduledExecutorService scheduledExecutorService) {
        if (TtlAgent.isTtlAgentLoaded() || scheduledExecutorService == null || scheduledExecutorService instanceof TtlEnhanced) {
            return scheduledExecutorService;
        }
        // 包装ScheduledExecutorService
        return new ScheduledExecutorServiceTtlWrapper(scheduledExecutorService, true);
    }

}

下面看一下几个包装的 Wrapper 的 executesubmit 方法

class ExecutorTtlWrapper implements Executor, TtlWrapper<Executor>, TtlEnhanced {
    @Override
    public void execute(@NonNull Runnable command) {
        // 通过TtlRunnable对原Runnable进行包装
        executor.execute(TtlRunnable.get(command, false, idempotent));
    }
    
    // ...
}
class ExecutorServiceTtlWrapper extends ExecutorTtlWrapper implements ExecutorService, TtlEnhanced {
    
    @NonNull
    @Override
    public <T> Future<T> submit(@NonNull Callable<T> task) {
        // 通过TtlCallable对原Callable进行包装
        return executorService.submit(TtlCallable.get(task, false, idempotent));
    }

    @NonNull
    @Override
    public Future<?> submit(@NonNull Runnable task) {
         // 通过TtlRunnable对原Runnable进行包装
        return executorService.submit(TtlRunnable.get(task, false, idempotent));
    }
    
    // ...
    
}
class ScheduledExecutorServiceTtlWrapper extends ExecutorServiceTtlWrapper implements ScheduledExecutorService, TtlEnhanced {

    @NonNull
    @Override
    public ScheduledFuture<?> schedule(@NonNull Runnable command, long delay, @NonNull TimeUnit unit) {
        // 通过TtlRunnable对原Runnable进行包装
        return scheduledExecutorService.schedule(TtlRunnable.get(command, false, idempotent), delay, unit);
    }

    @NonNull
    @Override
    public <V> ScheduledFuture<V> schedule(@NonNull Callable<V> callable, long delay, @NonNull TimeUnit unit) {
        // 通过TtlCallable对原Callable进行包装
        return scheduledExecutorService.schedule(TtlCallable.get(callable, false, idempotent), delay, unit);
    }
    
    // ...

}

可以看到,几个包装的 Wrapper 的 executesubmit 方法最后都通过 TtlRunnableTtlCallable 包装了原任务。

四、源码分析 - TtlRunnable

TtlCallableTtlRunnable 差不多,这里以 TtlRunnable 为例分析。

public final class TtlRunnable implements Runnable, TtlWrapper<Runnable>, TtlEnhanced, TtlAttachments {
    
}

1、get 方法

// com.alibaba.ttl.TtlRunnable

public static TtlRunnable get(@Nullable Runnable runnable, boolean releaseTtlValueReferenceAfterRun, boolean idempotent) {
    if (runnable == null) return null;

    if (runnable instanceof TtlEnhanced) {
        // avoid redundant decoration, and ensure idempotency
        if (idempotent) return (TtlRunnable) runnable;
        else throw new IllegalStateException("Already TtlRunnable!");
    }

    // 返回TtlRunnable
    return new TtlRunnable(runnable, releaseTtlValueReferenceAfterRun);
}

private TtlRunnable(@NonNull Runnable runnable, boolean releaseTtlValueReferenceAfterRun) {
    this.capturedRef = new AtomicReference<Object>(capture());
    // 原Runnable
    this.runnable = runnable;
    this.releaseTtlValueReferenceAfterRun = releaseTtlValueReferenceAfterRun;
}

这里的capture()方法调用的是Transmitter中的capture()方法

2、run 方法

// com.alibaba.ttl.TtlRunnable

public void run() {
    // 获取captured(就是Snapshot对象),里面存储了父线程的值
    final Object captured = capturedRef.get();
    if (captured == null || releaseTtlValueReferenceAfterRun && !capturedRef.compareAndSet(captured, null)) {
        throw new IllegalStateException("TTL value reference is released after run!");
    }
    // 传入capture方法捕获的ttl,然后在子线程重放,也就是调用ttl的set方法,
    // 这样就会把值设置到当前的线程中去,最后会把子线程之前存在的ttl返回
    final Object backup = replay(captured);
    try {
        // 调用被包装的 runnable 对象的 run() 方法执行实际的任务。
        runnable.run();
    } finally {
        // 恢复备份
        restore(backup);
    }
}

这里的replayrestore 方法 调用的也是Transmitter中的replayrestore 方法

五、源码分析 - Transmitter

上面说到,TtlRunnablegetrun 方法调用了 Transmitter 中的capture()replayrestore 方法

// com.alibaba.ttl.TransmittableThreadLocal

private static final Set<Transmittee<Object, Object>> transmitteeSet = new CopyOnWriteArraySet<>();

public static class Transmitter {

    @NonNull
    public static Object capture() {
        final HashMap<Transmittee<Object, Object>, Object> transmittee2Value = newHashMap(transmitteeSet.size());

        // 遍历 transmitteeSet
        for (Transmittee<Object, Object> transmittee : transmitteeSet) {
            try {
                // 调用 transmittee 的 capture 方法
                transmittee2Value.put(transmittee, transmittee.capture());
            } catch (Throwable t) {
                // ...
            }
        }

        // 构建 Snapshot
        return new Snapshot(transmittee2Value);
    }

    @NonNull
    public static Object replay(@NonNull Object captured) {
        // captured -> Snapshot
        final Snapshot capturedSnapshot = (Snapshot) captured;

        final HashMap<Transmittee<Object, Object>, Object> transmittee2Value = newHashMap(capturedSnapshot.transmittee2Value.size());

        // 遍历 Snapshot 中的 transmittee2Value
        for (Map.Entry<Transmittee<Object, Object>, Object> entry : capturedSnapshot.transmittee2Value.entrySet()) {
            Transmittee<Object, Object> transmittee = entry.getKey();
            try {
                Object transmitteeCaptured = entry.getValue();
                // 调用 transmittee 的 replay 方法
                transmittee2Value.put(transmittee, transmittee.replay(transmitteeCaptured));
            } catch (Throwable t) {
                // ...
            }
        }

        // 构建新的Snapshot
        return new Snapshot(transmittee2Value);
    }

    public static void restore(@NonNull Object backup) {
        // backup -> Snapshot,遍历 Snapshot 中的 transmittee2Value
        for (Map.Entry<Transmittee<Object, Object>, Object> entry : ((Snapshot) backup).transmittee2Value.entrySet()) {
            Transmittee<Object, Object> transmittee = entry.getKey();
            try {
                Object transmitteeBackup = entry.getValue();
                // 调用 transmittee 的 restore 方法
                transmittee.restore(transmitteeBackup);
            } catch (Throwable t) {
                // ...
            }
        }
    }

    private static class Snapshot {
        // key是Transmittee的实现,value是HashMap(存储了TransmittableThreadLocal及其值)
        final HashMap<Transmittee<Object, Object>, Object> transmittee2Value;

        public Snapshot(HashMap<Transmittee<Object, Object>, Object> transmittee2Value) {
            this.transmittee2Value = transmittee2Value;
        }
    }

}

可以看到 Transmitter 中的 capture()replayrestore 方法,都是在操作 Snapshot

  • Snapshot 保存着 HashMap<Transmittee<Object, Object>, Object> transmittee2Value
  • 调用的是 Transmitteecapture()replayrestore 方法

六、源码分析 - Transmittee

1、Transmittee 接口

// com.alibaba.ttl.TransmittableThreadLocal

public interface Transmittee<C, B> {
    @NonNull
    C capture();

    @NonNull
    B replay(@NonNull C captured);

    @NonNull
    B clear();

    void restore(@NonNull B backup);
}

2、transmitteeSet 怎么来的

// com.alibaba.ttl.TransmittableThreadLocal

private static final Set<Transmittee<Object, Object>> transmitteeSet = new CopyOnWriteArraySet<>();

// 注册 transmitteeSet
static {
    registerTransmittee(ttlTransmittee);
    registerTransmittee(threadLocalTransmittee);
}

public static <C, B> boolean registerTransmittee(@NonNull Transmittee<C, B> transmittee) {
    return transmitteeSet.add((Transmittee<Object, Object>) transmittee);
}

public static <C, B> boolean registerTransmittee(@NonNull Transmittee<C, B> transmittee) {
    return transmitteeSet.add((Transmittee<Object, Object>) transmittee);
}


// 匿名内部类
private static final Transmittee<HashMap<TransmittableThreadLocal<Object>, Object>, HashMap<TransmittableThreadLocal<Object>, Object>> ttlTransmittee =
    new Transmittee<HashMap<TransmittableThreadLocal<Object>, Object>, HashMap<TransmittableThreadLocal<Object>, Object>>() {
    // 实现了Transmittee的几个接口...
}

// 匿名内部类
private static final Transmittee<HashMap<ThreadLocal<Object>, Object>, HashMap<ThreadLocal<Object>, Object>> threadLocalTransmittee =
    new Transmittee<HashMap<ThreadLocal<Object>, Object>, HashMap<ThreadLocal<Object>, Object>>() {
    // 实现了Transmittee的几个接口...
}

3、ttlTransmittee

1)capture

// com.alibaba.ttl.TransmittableThreadLocal.ttlTransmittee

@NonNull
@Override
public HashMap<TransmittableThreadLocal<Object>, Object> capture() {
    final HashMap<TransmittableThreadLocal<Object>, Object> ttl2Value = newHashMap(holder.get().size());
    // 遍历 holder 中的 TransmittableThreadLocal
    for (TransmittableThreadLocal<Object> threadLocal : holder.get().keySet()) {
        // copyValue 实际是调用了 TransmittableThreadLocal 的 get方法
        ttl2Value.put(threadLocal, threadLocal.copyValue());
    }
    return ttl2Value;
}
// com.alibaba.ttl.TransmittableThreadLocal

private T copyValue() {
    return copy(get());
}

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

public T copy(T parentValue) {
    return parentValue;
}

2)replay

// com.alibaba.ttl.TransmittableThreadLocal.ttlTransmittee

@NonNull
@Override
public HashMap<TransmittableThreadLocal<Object>, Object> replay(@NonNull HashMap<TransmittableThreadLocal<Object>, Object> captured) {
    // 备份
    final HashMap<TransmittableThreadLocal<Object>, Object> backup = newHashMap(holder.get().size());

    // 遍历 holder 中的 TransmittableThreadLocal
    for (final Iterator<TransmittableThreadLocal<Object>> iterator = holder.get().keySet().iterator(); iterator.hasNext(); ) {
        TransmittableThreadLocal<Object> threadLocal = iterator.next();

        // backup
        backup.put(threadLocal, threadLocal.get());

        // clear the TTL values that is not in captured
        // avoid the extra TTL values after replay when run task
        if (!captured.containsKey(threadLocal)) {
            iterator.remove();
            threadLocal.superRemove();
        }
    }

    // set TTL values to captured
    setTtlValuesTo(captured);

    // call beforeExecute callback
    doExecuteCallback(true);

    return backup;
}
// com.alibaba.ttl.TransmittableThreadLocal

private static void setTtlValuesTo(@NonNull HashMap<TransmittableThreadLocal<Object>, Object> ttlValues) {
    for (Map.Entry<TransmittableThreadLocal<Object>, Object> entry : ttlValues.entrySet()) {
        TransmittableThreadLocal<Object> threadLocal = entry.getKey();
        threadLocal.set(entry.getValue());
    }
}

private static void doExecuteCallback(boolean isBefore) {
    // copy TTL Instances to avoid `ConcurrentModificationException`
    // even adjust TTL instances in biz lifecycle callbacks(beforeExecute/afterExecute)
    WeakHashMap<TransmittableThreadLocal<Object>, ?> ttlInstances = new WeakHashMap<TransmittableThreadLocal<Object>, Object>(holder.get());

    for (TransmittableThreadLocal<Object> threadLocal : ttlInstances.keySet()) {
        try {
            if (isBefore) threadLocal.beforeExecute();
            else threadLocal.afterExecute();
        } catch (Throwable t) {
            // ...
        }
    }
}

3)restore

// com.alibaba.ttl.TransmittableThreadLocal.ttlTransmittee

@Override
public void restore(@NonNull HashMap<TransmittableThreadLocal<Object>, Object> backup) {
    // call afterExecute callback
    doExecuteCallback(false);

    // 遍历 holder 中的 TransmittableThreadLocal
    for (final Iterator<TransmittableThreadLocal<Object>> iterator = holder.get().keySet().iterator(); iterator.hasNext(); ) {
        TransmittableThreadLocal<Object> threadLocal = iterator.next();

        // clear the TTL values that is not in backup
        // avoid the extra TTL values after restore
        if (!backup.containsKey(threadLocal)) {
            iterator.remove();
            threadLocal.superRemove();
        }
    }

    // restore TTL values
    setTtlValuesTo(backup);
}
// com.alibaba.ttl.TransmittableThreadLocal

private static void setTtlValuesTo(@NonNull HashMap<TransmittableThreadLocal<Object>, Object> ttlValues) {
    for (Map.Entry<TransmittableThreadLocal<Object>, Object> entry : ttlValues.entrySet()) {
        TransmittableThreadLocal<Object> threadLocal = entry.getKey();
        threadLocal.set(entry.getValue());
    }
}

  • 7
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

scj1022

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值