InheritableThreadLocal详解

简介

在之前我们详细介绍了ThreadLocalarrow-up-right,原理及设计,从源码层面上分析了ThreadLocal。但是它只能解决当前线程的信息传递,当然 ThreadLocal的最初设计也是这样的,但当我们需要将当先信息传递给子线程时ThreadLocal已经明显无法满足。这时InheritableThreadLocal 就显得尤为重要!


应用

为什么今天会谈到InheritableThreadLocal呢?这还是应为在项目上使用线程池的时候发现,子线程无法获取前端信息的信息,导致程序出错.......

InheritableThreadLocal 真的可以将当前线程的信息传递给子线程吗?我们可以模拟一下,同时与ThreadLocal进行对比

public class Test {
    public static void main(String[] args) {
        InheritableThreadLocal<String> inheritableThreadLocal = new InheritableThreadLocal<>();
        inheritableThreadLocal.set("haiji");
        ThreadLocal<String> threadLocal = new ThreadLocal<>();
        threadLocal.set("java有货");

        ExecutorService executorService = Executors.newSingleThreadExecutor();
        executorService.execute(()->{
            System.out.println("当前线程的名字:"+Thread.currentThread().getName());
            System.out.println("从 threadLocal 内获取值:"+threadLocal.get());
            System.out.println("从 inheritableThreadLocal 内获取值:"+inheritableThreadLocal.get());
        });
    }
}

验证的结果输出:

当前线程的名字:pool-1-thread-1 从 threadLocal 内获取值:null 从 inheritableThreadLocal 内获取值:haiji


InheritableThreadLocal 的原理

首先我们看看 InheritableThreadLocal 的源码

源码很简单,重载了 getMapcreateMap,我们想了解原理还是需要从 Thread 这个类进行,Thread内部维护了两个重要的变量 threadLocals / inheritableThreadLocals

Thread类中包含 threadLocalsinheritableThreadLocals 两个变量,其中 inheritableThreadLocals 即主要存储可自动向子线程中传递的ThreadLocal.ThreadLocalMap。 接下来看一下父线程创建子线程的流程,我们从最简单的方式说起:

4.1、用户创建Thread

4.2、Thread创建

4.3、Thread初始化

可以看到,采用默认方式产生子线程时,inheritThreadLocals=true;若此时父线程inheritableThreadLocals不为空,则将父线程inheritableThreadLocals传递至子线程。

4.4、ThreadLocal.createInheritedMap

让我们继续追踪createInheritedMap:

从ThreadLocalMap可知,子线程将parentMap中的所有记录逐一复制至自身线程。

Last updated

Was this helpful?