一、java子線程中獲取父線程的threadLocal中的值
threadLocal可以做線程級的數據隔離,那如何在子線程中獲取父線程的值呢? 可以使用InheritableThreadLocal
/** * Java子線程獲取父線程的threadLocal中的值 */ public class ThreadDemo1 { public static final InheritableThreadLocal<String> inheritableThreadLocal = new InheritableThreadLocal<>(); public static final ThreadLocal<String> threadLocal = new ThreadLocal<>(); public static void main(String[] args) throws Exception { inheritableThreadLocal.set("inheritableThreadLocal hello"); threadLocal.set("threadLocal world"); new Thread(()->{ System.out.println(String.format("子線程可繼承值:%s", inheritableThreadLocal.get())); System.out.println(String.format("子線程值:%s", threadLocal.get())); new Thread(()->{ System.out.println(String.format("孫線程可繼承值:%s", inheritableThreadLocal.get())); System.out.println(String.format("孫線程值:%s", threadLocal.get())); }).start(); }).start(); Thread.sleep(3000); System.out.println("--------------修改可繼承值threadLocal和threadLocal的值--------------------"); inheritableThreadLocal.set("inheritableThreadLocal hello2"); threadLocal.set("threadLocal world2"); new Thread(()->{ System.out.println(String.format("子線程可繼承值:%s", inheritableThreadLocal.get())); System.out.println(String.format("子線程值:%s", threadLocal.get())); new Thread(()->{ System.out.println(String.format("孫線程可繼承值:%s", inheritableThreadLocal.get())); System.out.println(String.format("孫線程值:%s", threadLocal.get())); }).start(); }).start(); } }
輸出結果如下:
子線程可繼承值:inheritableThreadLocal hello 子線程值:null 孫線程可繼承值:inheritableThreadLocal hello 孫線程值:null --------------修改可繼承值threadLocal和threadLocal的值-------------------- 子線程可繼承值:inheritableThreadLocal hello2 子線程值:null 孫線程可繼承值:inheritableThreadLocal hello2 孫線程值:null
說明在子線程和孫線程中可以獲取到父線程的 inheritableThreadLocal 的值。修改inheritableThreadLocal 的值后,子線程和孫線程中同樣可以獲取到父線程的inheritableThreadLocal 的值。
但是threadLocal卻不行,獲取到的值為空。
2、查看創建Thread的源碼
private void init(ThreadGroup g, Runnable target, String name, long stackSize, AccessControlContext acc, boolean inheritThreadLocals) { ...... if (inheritThreadLocals && parent.inheritableThreadLocals != null) this.inheritableThreadLocals = ThreadLocal.createInheritedMap(parent.inheritableThreadLocals); /* Stash the specified stack size in case the VM cares */ this.stackSize = stackSize; /* Set thread ID */ tid = nextThreadID(); } //ThreadLocal.createInheritedMap static ThreadLocalMap createInheritedMap(ThreadLocalMap parentMap) { return new ThreadLocalMap(parentMap); }
可以看到,創建線程時,調用了init方法,然后將父線程的inheritableThreadLocals賦值inheritableThreadLocals (ThreadLocal.ThreadLocalMap inheritableThreadLocals = null;)