TransmittableThreadLocal详解,源码分析,一文带你掌握核心逻辑

TransmittableThreadLocal详解,源码分析,一文带你掌握核心逻辑

这篇文章主要想向大家介绍TransmittableThreadLocal的基本原理,具体应用其实就是在使用线程池的时候支持threadLocal的子线程传递

大家可能会说Jdk自带的InheritableThreadLocal不是已经实现了ThreadLocal的传递吗?为什么还需要TransmittableThreadLocal。
如果大家有看过InheritableThreadLocal的源代码就会发现,InheritableThreadLocal的传递是发生在新建线程的时候,但是在我们项目中基本都是用线程池来使用多线程,因为线程的创建销毁都会有资源消耗,当然也有可能发生oom,具体就不多说了。
TransmittableThreadLocal就解决了线程池维度下的ThreadLocal传递,大家可以浅浅思考一下怎么改变一下,就可以实现线程复用的情况下也可以传递ThreadLocal。
其实就是把传递ThreadLocal的逻辑放在run方法的前面就解决了,思想就是这么简单,但是却很巧妙,使用装饰者模式把Runnable包了一层

源码分析

TransmittableThreadLocal

首先很重要的是TransmittableThreadLocal里面保存了一个静态变量holder,大家得先理解好holder
holder 变量是一个InheritableThreadLocal, 他是一个map但是一直都是当作Set在用,value一直是空

The value of holder is type WeakHashMap<TransmittableThreadLocal, ?>, but it is used as Set (aka. do NOT use about value, always null).

每次使用holder变量都会带着.get() ,意味着每次获取到的WeakHashMap都是线程自己的,这是我之前一直不理解的点,记住,每次使用holder都会带上.get(),而不是真正全局使用一个WeakHashMap

接下来来分析一下set()方法

  1. 首先会将当前的value设置到Thread中的ThreadLocalMap

  2. 然后将当前的TransmittableThreadLocal放入当前线程的map中(给未来打快照使用)

public final void set(T value) {
   
  // 首先先使用ThreadLocal的特性,将当前的value设置到Thread中的ThreadLocalMap,保证ThreadLocal的特性被保留
  super.set(value);
  // may set null to remove value
  // 如果是value是null,就从map中删除
  if (null == value) removeValue();
  // 这一步本质就是将当前的TransmittableThreadLocal放入当前线程的map中,以保存父线程的使用过的TransmittableThreadLocal
  else addValue();
}

private void addValue() {
   
  if (!holder.get().containsKey(this)) {
   
    // 将当前的TransmittableThreadLocal放入当前线程的map中
    // 这里value一直是空
    holder.get().put((TransmittableThreadLocal<Object>) this, null); // WeakHashMap supports null value.
  }
}

get()方法没有什么特殊的大家看看就行

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

TtlRunnable

重要!!!

我认为整个TransmittableThreadLocal的核心就是使用装饰模式,将整个Runnable 包装了一层,实现了当线程复用的情况也可以将父线程继承到子线程的能力

首先在使用TtlRunnable.get(runnable),会将Runnable包装一层,此时的调用方就是父线程,在方法中会调用capture(),获取当前父线程的快照

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

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

// 构造函数
private TtlRunnable(@NonNull Runnable runnable, boolean releaseTtlValueReferenceAfterRun) {
   
  // capture()此方法是核心
  this.capturedRef = new AtomicReference<Object>(capture());
  this</
  • 12
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值