java子线程中获取父线程的threadLocal中的值
1 package com.example.springbootstudy.test.threadLocal; 2 3 public class BaseTest { 4 5 public static final InheritableThreadLocal<String> inheritableThreadLocal = new InheritableThreadLocal<>(); 6 7 public static final ThreadLocal<String> threadLocal = new ThreadLocal<>(); 8 9 public static void main(String[] args) { 10 inheritableThreadLocal.set("Inheritable hello"); 11 threadLocal.set("hello"); 12 13 new Thread(() -> { 14 System.out.println(String.format("子线程可继承值:%s", inheritableThreadLocal.get())); 15 System.out.println(String.format("子线程值:%s", threadLocal.get())); 16 17 new Thread(() -> { 18 System.out.println(String.format("孙子线程可继承值:%s", inheritableThreadLocal.get())); 19 System.out.println(String.format("孙子线程值:%s", threadLocal.get())); 20 }).start(); 21 }).start(); 22 23 System.out.println(String.format("主线程-inheritableThreadLocal:%s", inheritableThreadLocal.get())); 24 System.out.println(String.format("主线程-threadLocal:%s", threadLocal.get())); 25 } 26 27 }
运行结果如下所示:
子线程可继承值:Inheritable hello 主线程-inheritableThreadLocal:Inheritable hello 子线程值:null 主线程-threadLocal:hello 孙子线程可继承值:Inheritable hello 孙子线程值:null
InheritableThreadLocal 是如何做到的呢?
我们先看下类结构
public class Thread{ ThreadLocal.ThreadLocalMap inheritableThreadLocals = null; } public class InheritableThreadLocal<T> extends ThreadLocal<T> { ThreadLocalMap getMap(Thread t) { return t.inheritableThreadLocals; } void createMap(Thread t, T firstValue) { t.inheritableThreadLocals = new ThreadLocalMap(this, firstValue); } }
这里重写了ThreadLocal的操作ThreadLocalMap的方法,其实就是把从Thread类操作threadLocals变量,切换到inheritableThreadLocals变量上。
这不就是跟ThreadLocal一样吗?只是换了个变量名! 但是实际上Thread类初始化时还有一些骚操作,请看:
1 public class Thread{ 2 public Thread(){ 3 if (inheritThreadLocals && parent.inheritableThreadLocals != null) 4 this.inheritableThreadLocals = ThreadLocal.createInheritedMap(parent.inheritableThreadLocals); 5 } 6 } 7 8 //ThreadLocal 类里的方法 9 static ThreadLocalMap createInheritedMap(ThreadLocalMap parentMap) { 10 return new ThreadLocalMap(parentMap); 11 }
这里判断父线程的inheritableThreadLocals有值, 就拷贝到当前子线程的inheritableThreadLocals , 这样我们就能在子线程获取到父线程的值了。
这里要注意的是,并不是复制的指针,而是复制了副本。你在子线程重新set值后, 并不会影响父线程的值。
郭慕荣博客园