java子线程中获取父线程的threadLocal中的值

发布时间 2023-06-03 17:07:00作者: 郭慕荣
 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值后, 并不会影响父线程的值。