ThreadLocal/InheritableThreadLocal/TransmittableThreadLocal对比

一、ThreacLocal

  1. 介绍
    1. 提供线程局部变量,这些局部变量只能由所在的线程访问(set/get);
    2. 线程隔离;
    3. 变量不能在传递到子线程中;
  2. 原理
    1. 在Thread中是一个ThreacLocal.ThreadLocalMap类型的属性 threadLocals,key为当前线程ID(Thread.currentThread()),value 为变量值。
  3. 代码
public class Thread implements Runnable {
    //...
    
    ThreadLocal.ThreadLocalMap threadLocals = null;

    //...
}
public class ThreadLocal<T> {
    //...

    // set
    public void set(T value) {
        Thread t = Thread.currentThread();
        ThreadLocalMap map = getMap(t);
        if (map != null) {
            map.set(this, value);
        } else {
            createMap(t, value);
        }
    }

    // create
    void createMap(Thread t, T firstValue) {
       t.threadLocals = new ThreadLocalMap(this, firstValue);
    }

    // get
    public T get() {
       Thread t = Thread.currentThread();
       ThreadLocalMap map = getMap(t);
       if (map != null) {
           ThreadLocalMap.Entry e = map.getEntry(this);
           if (e != null) {
               SuppressWarnings("unchecked")
               T result = (T)e.value;
               return result;
            }
        }
        return setInitialValue();
    }

    // get
    ThreadLocalMap getMap(Thread t) {
        return t.threadLocals;
    }

    //....
}

二、InheritableThreadLocal

  1. 介绍
    1. 继承ThreadLocal;
    2. 当创建一个子线程时,这个类提供所有从父线程继承来的局部线程变量;
    3. 实现父子线程局部变量的传递;父线程局部变量可以传递给子线程,子线程的局部变量不能传递给父线程;
    4. 使用线程池的场景中,因为线程池中的线程是可以复用的,如果线程局部变量没有及时清除,会导致新业务逻辑获取到上一个业务逻辑中的线程变量;
  2. 原理
    1. 在Thread中是一个ThreacLocal.ThreadLocalMap类型的属性 inheritableThreadLocals,key为当前线程ID(Thread.currentThread()),value 为变量值。
    2. 创建子线程时,根据父线程的inheritableThreadLocals为子线程的inheritableThreadLocals创建新的ThreadLocalMap实例;
    3. 重写getMap() 和 createMap(Thread t, T firstValue)
  3. 代码
public class Thread implements Runnable {
    //...
    
    ThreadLocal.ThreadLocalMap threadLocals = null;

    //...

    private Thread(ThreadGroup g, Runnable target, String name,
                   long stackSize, AccessControlContext acc,
                   boolean inheritThreadLocals) {
        //...

        if (inheritThreadLocals && parent.inheritableThreadLocals != null)
            this.inheritableThreadLocals =
                ThreadLocal.createInheritedMap(parent.inheritableThreadLocals);

        //...

    }

    //...

}
public class InheritableThreadLocal<T> {
    //...
    
    // get map.
    ThreadLocalMap getMap(Thread t) {
       return t.inheritableThreadLocals;
    }

    // creat map.
    void createMap(Thread t, T firstValue) {
        t.inheritableThreadLocals = new ThreadLocalMap(this, firstValue);
    }

}

三、TransmittableThreadLocal

  1. 介绍
    1. 继承InheritableThreadLocal,所以TransmittableThreadLocal首先是一个InheritableThreadLocal;
    2. 可以将变量从提交(submit)任务的线程传递到执行(run)任务的线程中。使用配合TtlExecutors.getTtlExecutorService()可以使子线程实时感知到父线程变量的变化;子线程对父线程值的修改只会影响当前运行时子线程,不影响父线程和其他子线程,也不影响下次运行;
    3. alibaba提供,需要添加第三方依赖;
  2. 原理
    1. 实现holder;
    2. TtlExecutors封装ExecutorService;
  3. 代码
    // Maven 依赖
    <dependency>
        <groupId>com.alibaba</groupId>
        <artifactId>transmittable-thread-local</artifactId>
        <version>2.10.2</version>
    </dependency>
public class TransmittableThreadLocal<T> extends InheritableThreadLocal<T> {

    //...


    @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);
        // may set null to remove value
        if (null == value) removeValue();
        else addValue();
    }

    @Override
    public final void remove() {
        removeValue();
        super.remove();
    }

    // Note about holder:
    // 1. The value of holder is type Map<TransmittableThreadLocal<?>, ?> (WeakHashMap implementation),
    //    but it is used as *set*.
    // 2. WeakHashMap support null value.
    private static InheritableThreadLocal<Map<TransmittableThreadLocal<?>, ?>> holder =
            new InheritableThreadLocal<Map<TransmittableThreadLocal<?>, ?>>() {
                @Override
                protected Map<TransmittableThreadLocal<?>, ?> initialValue() {
                    return new WeakHashMap<TransmittableThreadLocal<?>, Object>();
                }

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


    private void addValue() {
        if (!holder.get().containsKey(this)) {
            holder.get().put(this, null); // WeakHashMap supports null value.
        }
    }

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



    //...

}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

武力Coding

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

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

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

打赏作者

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

抵扣说明:

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

余额充值