子线程无法拿到父线程的变量怎么办?|Java 开发实战

本文正在参加「Java主题月 – Java 开发实战」,详情查看 活动链接

开篇

这是我参与更文挑战的第9天,活动详情查看: 更文挑战

数据在哪个线程存储,就要从哪个线程读取,子线程是读取不到的。那如果想要读取该怎么办呢?

示例

遇到开篇说的这种情况,可以使用InheritableThreadLocal来帮助我们解决这类问题,InheritableThreadLocalThreadLocal 的子类,我们用 InheritableThreadLocalThreadLocal来演示下效果,便于更直观的理解。

@Test
void contextLoads() throws InterruptedException {
    ThreadLocal threadLocal = new ThreadLocal();
    threadLocal.set("蒋老湿");
    System.out.println("threadLocal.get() = " + threadLocal.get());
    // 子线程是读取不到的
    new Thread(() -> {
        String name = Thread.currentThread().getName();
        System.out.println(String.format("this is sub thread name:%s, threadLocal.get(): %s", name, threadLocal.get()));
    }).start();

    Thread.sleep(1000);
    // ThreadLocal 修改为 InheritableThreadLocal
    ThreadLocal inheritableThreadLocal = new InheritableThreadLocal();
    inheritableThreadLocal.set("蒋老湿inheritableThreadLocal");
    System.out.println("inheritableThreadLocal.get() = " + inheritableThreadLocal.get());
    // 在子线程中也能获取到父线程 ThreadLocal 中的数据。
    new Thread(() -> {
        String name = Thread.currentThread().getName();
        System.out.println(String.format("this is sub thread name:%s, inheritableThreadLocal.get(): %s", name, inheritableThreadLocal.get()));
    }).start();
}
复制代码

image.png

InheritableThreadLocal解读

image.png
以上有三个方法,分别是:

  • getMap():方法的返回值变成了 inheritableThreadLocals对象
  • createMap(): 构建出 ThreadLocalMap 的对象复制给inheritableThreadLocals
  • childValue(): 这个方法仅仅返回它的输入参数,并且应该被覆盖

和 ThreadLocal 相比,主要是保存数据的对象从 threadLocals属性 变为 inheritableThreadLocals属性。

set过程

image.png

set方法会进入如下内容ThreadLocal#set(T value)

image.png
才是会调用java.lang.InheritableThreadLocal#createMap,也就是给Thread类的inheritableThreadLocals变量赋值。
image.png

childValue()是什么时候接口到参数的呢?

在创建子线程的时候,通过红框部分可以了解到,如果父线程存在 inheritableThreadLocals 变量且不为null,就调用 ThreadLocal.createInheritedMap() 为该线程的 inheritableThreadLocals 变量赋值。

image.png

ThreadLocal.createInheritedMap 方法所做的事情,其实就是将父线程的 inheritableThreadLocals 变量值赋值给子线程的 inheritableThreadLocals 变量。因此,在子线程中就可以访问到父线程 ThreadLocal 中的数据了。

这种复制不是实时同步,是在子线程创建的一瞬间才将父线程inheritableThreadLocals 变量的值赋值给子线程,一旦子线程创建成功后,用户再次去修改了父线程inheritableThreadLocals变量的值(即修改了父线程 ThreadLocal 中的数据),此时子线程是感知不到这个变化的。所以这里是值传递,不是引用传递。

好啦,经过上面的介绍大家应该搞清楚InheritableThreadLocal是怎么一会事了吧

关注+点赞?收藏❤️不迷路

文章每周持续更新,可以微信搜索「 十分钟学编程 」第一时间阅读和催更,如果这个文章写得还不错,觉得有点东西的话
各位的支持和认可,就是我创作的最大动力,我们下篇文章见!

© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享