InheritableThreadLocal类详解

我们在使用ThreadLocal类的时候,可以保证各个线程使用自己的数据,而不相互干扰。

但是如果我们有这样的一个需求,就是各个线程相互不干扰的情况下。各个线程的子线程可以访问到当前线程中的值。对于这个子线程来说就是访问父线程。

public class InheritableThreadLocal<T> extends ThreadLocal<T> {
我们可以从源码中看出InheritableThreadLocal类继承了ThreadLocal这个类。

也就是说,该类具备了ThreadLocal类的能力。

此时我们可以运行一个demo

public class InheritableThreadLocalTest {

    public static void main(String[] args) throws InterruptedException {
        InheritableThreadLocalContext inheritableThreadLocalContext = new InheritableThreadLocalContext();
        inheritableThreadLocalContext.setValue("123");
        System.out.println(inheritableThreadLocalContext.getValue());

    }
}

public class InheritableThreadLocalContext {

    public static ThreadLocal<String> threadLocal = new ThreadLocal<>();
    //可以获取父线程的数据
//    public static InheritableThreadLocal<String> threadLocal = new InheritableThreadLocal<>();
    public void setValue(String s) {
        threadLocal.set(s);
    }

    public String getValue() throws InterruptedException {

        /*

        final String[] s = {null};
        Runnable runnable = () -> s[0] = threadLocal.get();
        Thread t = new Thread(runnable);
        t.start();
        Thread.sleep(1000);
        return s[0];
        */
        return threadLocal.get();
    }
}

我们可以发现,当我在子线程中去访问ThreadLocal对象的值的时候,获取值的时候,是获取不到的。但是我们将ThreadLocal类替换成InheritableThreadLocal类的时候,此时是可以获取到值的。也就是说,在各个不相关的线程不相互干扰的情况下,实现了子线程获取父线程数据的能力。

也就是该InheritableThreadLocal类最大的能力。

我们可以看一看该类的实现。

public class InheritableThreadLocal<T> extends ThreadLocal<T> {
    /**
     * Computes the child's initial value for this inheritable thread-local
     * variable as a function of the parent's value at the time the child
     * thread is created.  This method is called from within the parent
     * thread before the child is started.
     * <p>
     * This method merely returns its input argument, and should be overridden
     * if a different behavior is desired.
     *
     * @param parentValue the parent thread's value
     * @return the child thread's initial value
     */
    protected T childValue(T parentValue) {
        return parentValue;
    }

    /**
     * Get the map associated with a ThreadLocal.
     *
     * @param t the current thread
     */
    ThreadLocalMap getMap(Thread t) {
       return t.inheritableThreadLocals;
    }

    /**
     * Create the map associated with a ThreadLocal.
     *
     * @param t the current thread
     * @param firstValue value for the initial entry of the table.
     */
    void createMap(Thread t, T firstValue) {
        t.inheritableThreadLocals = new ThreadLocalMap(this, firstValue);
    }
}

这里有两个方法createMap和 getMap。复写了父类ThreadLocal类的方法。有分析过ThreadLocal源码的朋友可以知道。ThraedLocal 对象的值是保存在一个自己实现的Map中的。然后绑定到当前的Thread对象的 threadLocals成员变量上。



这里我们可以看到一个inheritableThreadLocals成员变量。该成员变量是InheritableThreadLocal类用来存储父线程数据用的。稍后我们会提及




这里可以说明了,为什么ThreadLocal类可以保证每个线程访问的数据相互都不干扰,因为数据是绑定在线程对象本身的。

我们再到Thread类的 init方法中去看下

private void init(ThreadGroup g, Runnable target, String name,
                  long stackSize, AccessControlContext acc) {
    if (name == null) {
        throw new NullPointerException("name cannot be null");
    }

//中间忽略一些代码

if (parent.inheritableThreadLocals != null)
    this.inheritableThreadLocals =
        ThreadLocal.createInheritedMap(parent.inheritableThreadLocals);
/* Stash the specified stack size in case the VM cares */
上面代码的意思是如果父线程的InheritableThreadLocals成员变量不为空,将父线程的InheritableThreadLocals成员变量拷贝到当前线程的

InheritableThreadLocals变量上来。而且,在上面我们可以看到InheritableThreadLocal类复写了ThreadLocal类的getMap和createMap方法,故此可以拿到父线程的数据

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值