使用InheritableThreadLocal的细节

ThreadLocal不支持继承性,即在子线程中无法使用父线程的ThreadLocal,因此提供了InheritableThreadLocal来实现在子线程中也能使用父线程的ThreadLocal。

在使用InheritableThreadLocal时,应该注意,父线程中对InheritableThreadLocal变量的赋值要先于对子线程的定义,例如

        Runnable runnable = () ->{
            System.out.println("thread threadLocal is  " + threadLocal.get());
            System.out.println("thread inheritableThreadLocal is : " + inheritableThreadLocal.get());
        };

        Thread thread = new Thread(runnable);
        threadLocal.set("threadLocal is only found in main thread");
        inheritableThreadLocal.set("inheritableThreadLocal can be found in both thread and main thread!");

上述方式中,子线程同样访问不到父线程中的inheritableThreadLocal,但是换成如下方式则可以访问到。

        Runnable runnable = () ->{
            System.out.println("thread threadLocal is  " + threadLocal.get());
            System.out.println("thread inheritableThreadLocal is : " + inheritableThreadLocal.get());
        };

        threadLocal.set("threadLocal is only found in main thread");
        inheritableThreadLocal.set("inheritableThreadLocal can be found in both thread and main thread!");
        Thread thread = new Thread(runnable);

为什么会出现这样的情况?看一下Thread构造函数的源码:

    public Thread(Runnable target) {
        init(null, target, "Thread-" + nextThreadNum(), 0);
    }

    private void init(ThreadGroup g, Runnable target, String name,long stackSize, AccessControlContext acc) {
        
        //...
        
        Thread parent = currentThread();
        
        //...

        if (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默认值null,只有在调用ThreadLocal的set方法时,线程才会创建ThreadLocal,inheritableThreadLocal继承自ThreadLocal,所以也是同样的方式创建的。

如果我们在父线程中,对threadLocal.set()晚于子线程的定义Thread thread = new Thread(runnable),那么在创建子线程的init()方法中可以看到,Thread parent = currentThread();获取父线程,由于此时父线程对threadLocal的赋值在子线程的定义之后,因此理所当然的parent.inheritableThreadLocals == null 成立,所以子线程中也就没有InheritableThreadLocal了,也就无法在子线程中使用父线程的InheritableThreadLocal。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值