ThreadLocal (三):为何TransmittableThreadLocal

一、示例

 线程池内的线程并没有父子关系,所以不适合InheritableThreadLocal的使用场景

public class ThreadPoolInheritableThreadLocalDemo {

//    static ThreadLocal<String> threadLocal = new InheritableThreadLocal<>();
//    static ExecutorService pool = Executors.newFixedThreadPool(2);

    static TransmittableThreadLocal<String> threadLocal = new TransmittableThreadLocal<>();
    static ExecutorService pool =  TtlExecutors.getTtlExecutorService(Executors.newFixedThreadPool(3));

    public static void main(String[] args) {
        for(int i=0;i<100;i++) {
            int j = i;
            pool.execute(new Thread(new Runnable() {
                @Override
                public void run() {
                    ThreadPoolInheritableThreadLocalDemo.threadLocal.set("superWorld"+j);

                    ThreadPoolInheritableThreadLocalDemo.pool.execute(new Runnable() {
                        @Override
                        public void run() {
                            System.out.println(Thread.currentThread().getName()  +
                                    " : " +
                                    ThreadPoolInheritableThreadLocalDemo.threadLocal.get());
                        }
                    });
                }
            }));
        }
    }

}

二、TransmittableThreadLocal实现分析

读取线程间传递的ThreadLocal 值比较麻烦,ThreadLocal 和 InheritableThreadLocal 都没有开放内部的 ThreadLocalMap,不能直接读取。

所以要么自己完全实现一套 ThreadLocalMap 机制(如 Netty 的 FastThreadLocal),要么就是自己实现 ThreadLocal 的子类,在每次调用 ThreadLocal

的 set/get/remove 等接口的时候,为 Thread 记录到底绑定了哪些需要发生线程间传递的 ThreadLocal 对象。

/**
    *实际存储值的工作还是父类ThreadLocal完成
    *TransmittableThreadLocal 只是记录了哪些线程使用了TransmittableThreadLocal对象
    */
    @Override
    public final void set(T value) {
        super.set(value);
        if (null == value) { // may set null to remove value
            removeValue();
        } else {
            addValue();
        }
    }/**
    *holder 只是为了记录使用了哪些 TransmittableThreadLocal 对象
    *在构造TtlRunnable/TtlCallable 的时候, 通过holder取得对应的TransmittableThreadLocal
   *InheritableThreadLocal的默认值是WeakHashMap
*/ 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); }

调用ThreadPoolInheritableThreadLocalDemo.threadLocal.set("superWorld"+j)时, 

holder.get().containskey(this) 为false

2. TtlRunnable

 构造TtlRunable时,设置线程对应的Map<TransmittableThreadLocal<?>, Object>>

    private TtlRunnable(Runnable runnable, boolean releaseTtlValueReferenceAfterRun) {
     //
this.copiedRef = new AtomicReference<Map<TransmittableThreadLocal<?>, Object>>(TransmittableThreadLocal.copy()); this.runnable = runnable; this.releaseTtlValueReferenceAfterRun = releaseTtlValueReferenceAfterRun; }
TransmittableThreadLocal.copy
    static Map<TransmittableThreadLocal<?>, Object> copy() {
        Map<TransmittableThreadLocal<?>, Object> copy = new HashMap<TransmittableThreadLocal<?>, Object>();
        for (TransmittableThreadLocal<?> threadLocal : holder.get().keySet()) {
            copy.put(threadLocal, threadLocal.copyValue());
        }
        return copy;
    }

3.运行时,备份和恢复Map<TransmittableThreadLocal<?>, Object>

TtlRunnable#run

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

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

参考:

transmittableThreadLocal

原文地址:https://www.cnblogs.com/yuyutianxia/p/3983476.html