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); } }
参考: