解决ThreadLocal在开启子线程时,父线程向子线程值传递问题

1. java.lang.ThreadLocal

数据存储在当前线程的Thread.threadLocals里,是ThreadLocalMap数据结构,开启子线程时值传递就会丢失

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

    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();
    }

2. java.lang.InheritableThreadLocal

数据存储在当前线程的Thread.inheritableThreadLocals里,是ThreadLocalMap数据结构,开启子线程时值可以传递,是因为创建线程时进行了重新赋值,但是在线程池字面会丢失。

java.lang.Thread#init(java.lang.ThreadGroup, java.lang.Runnable, java.lang.String, long, java.security.AccessControlContext, boolean)

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

    
ThreadLocalMap getMap(Thread t) {
       return t.inheritableThreadLocals;
}

3. com.alibaba.ttl.TransmittableThreadLocal 

需要结合com.alibaba.ttl.threadpool.TtlExecutors使用,是阿里开源的专门用以解决上述问题的类,直接对原生的runnable进行了包装在初始化runnable时将父线程的值进行重新赋值

com.alibaba.ttl.TransmittableThreadLocal

    public final void set(T value) {
        if (!disableIgnoreNullValueSemantics && null == value) {
            // may set null to remove value
            remove();
        } else {
            super.set(value);
            addThisToHolder();
        }
    }

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


ExecutorService threadPool= TtlExecutors.getTtlExecutorService(Executors.newFixedThreadPool(12));


com.alibaba.ttl.threadpool.ExecutorTtlWrapper#execute
    @Override
    public void execute(@NonNull Runnable command) {
        executor.execute(TtlRunnable.get(command));
    }

com.alibaba.ttl.TtlRunnable#TtlRunnable

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


<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>transmittable-thread-local</artifactId>
    <version>2.11.4</version>
</dependency>

参考原文:https://blog.csdn.net/qq_26012495/article/details/104379137

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值