TransmittableThreadLocal详解
1、簡介
TransmittableThreadLocal 是Alibaba開源的、用于解決 “在使用線程池等會緩存線程的組件情況下傳遞ThreadLocal” 問題的 InheritableThreadLocal 擴展。若希望 TransmittableThreadLocal 在線程池與主線程間傳遞,需配合 TtlRunnable 和 TtlCallable 使用。
2、使用場景
下面是幾個典型場景例子。
3、源碼分析
TransmittableThreadLocal 繼承自 InheritableThreadLocal,這樣可以在不破壞ThreadLocal 本身的情況下,使得當用戶利用 new Thread() 創建線程時仍然可以達到傳遞InheritableThreadLocal 的目的。
public class TransmittableThreadLocal<T> extends InheritableThreadLocal<T> { ...... }TransmittableThreadLocal 相比較 InheritableThreadLocal 很關鍵的一點改進是引入holder變量,這樣就不必對外暴露Thread中的 inheritableThreadLocals(參考InheritableThreadLocal詳解),保持ThreadLocal.ThreadLocalMap的封裝性。
// 理解holder,需注意如下幾點: // 1、holder 是 InheritableThreadLocal 變量; // 2、holder 是 static 變量; // 3、value 是 WeakHashMap; // 4、深刻理解 ThreadLocal 工作原理; private static InheritableThreadLocal<Map<TransmittableThreadLocal>, > holder =new InheritableThreadLocal<Map<TransmittableThreadLocal>, >() {@Overrideprotected Map<TransmittableThreadLocal>, initialValue() {return new WeakHashMap<>();}@Overrideprotected Map<TransmittableThreadLocal>, childValue(Map<TransmittableThreadLocal>, parentValue) {return new WeakHashMap<>(parentValue);}};個人認為 holder 變量的設計,極大體現了作者的智慧,讓人無數次獻上膝蓋。。。
// 調用 get() 方法時,同時將 this 指針放入 holder public final T get() {T value = super.get();if (null != value) {addValue();}return value; } void addValue() {if (!holder.get().containsKey(this)) {holder.get().put(this, null); // WeakHashMap supports null value.} } // 調用 set() 方法時,同時處理 holder 中 this 指針 public final void set(T value) {super.set(value);if (null == value) { // may set null to remove valueremoveValue();} else {addValue();} } void removeValue() {holder.get().remove(this); }4、工作流程簡介
自定義 TtlRunnable 實現 Runnable,TtlRunnable初始化方法中保持當前線程中已有的TransmittableThreadLocal
private TtlRunnable(Runnable runnable, boolean releaseTtlValueReferenceAfterRun) {this.copiedRef = new AtomicReference<Map<TransmittableThreadLocal<?>, Object>>(TransmittableThreadLocal.copy());this.runnable = runnable;this.releaseTtlValueReferenceAfterRun = releaseTtlValueReferenceAfterRun; }線程池中線程 調用run方法,執行前先backup holder中所有的TransmittableThreadLocal, copiedRef中不存在,holder存在的,說明是后來加進去的,remove掉holder中的;將copied中的TransmittableThreadLocal set到當前線程中
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);} }執行后再恢復 backup 的數據到 holder 中(backup中不存在,holder中存在的TransmittableThreadLocal,從holder中remove掉),將 backup 中的 TransmittableThreadLocal set到當前線程中
5、參考文獻
作者:沈淵
鏈接:https://www.jianshu.com/p/e0774f965aa3
來源:簡書
簡書著作權歸作者所有,任何形式的轉載都請聯系作者獲得授權并注明出處。 創作挑戰賽新人創作獎勵來咯,堅持創作打卡瓜分現金大獎
總結
以上是生活随笔為你收集整理的TransmittableThreadLocal详解的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 何为TransmittableThrea
- 下一篇: FastThreadLocal原理