ThreadLocal变量和InheritableThreadLocal变量

TheadLocal线程局部变量

为每一个使用变量的线程都提供一个变量值的副本,每个线程都可以独立地改变自己的副本,而不会和其他线程冲突。

ThreadLocal类有一个protected方法initialValue()和三个public方法get(),set(T),remove(),其他的私有方法暂不讨论,主要看一下3个公有方法的实现原理:

set(T)

    public void set(T value) {
        Thread t = Thread.currentThread();
        # 每个线程有自己维护的一个ThreadLocalMap
        ThreadLocalMap map = getMap(t);
        # 如果存在就把当前值放入线程的Map中,key为当前ThreadLocal类的实例
        if (map != null)
            map.set(this, value);
        else
        # 如果不存在就创建这个Map,然后将ThreadLocal实例作为key
            createMap(t, value);
    }

T get()

    public T get() {
        Thread t = Thread.currentThread();
        ThreadLocalMap map = getMap(t);
        # 根据当前的ThreadLocal实例获得存入的value值
        if (map != null) {
            ThreadLocalMap.Entry e = map.getEntry(this);
            if (e != null) {
                @SuppressWarnings("unchecked")
                T result = (T)e.value;
                return result;
            }
        }
        # 如果不存在就返回一个初始值
        return setInitialValue();
    }

remove()

    public void remove() {
         # 获得当前线程的Map
         ThreadLocalMap m = getMap(Thread.currentThread());
         # 根据当前ThreadLocal实例移除Map中的值
         if (m != null)
             m.remove(this);
     }

ThreadLocal(以空间换时间)和线程同步机制(以时间换空间)都是为了解决多线程中相同变量的访问冲突问题。

InheritableThreadLocal

从上面已经知道ThreadLocal主要是依据Thread.currentThread()拿到线程的ThreadLocalMap变量,进而得到之前set的值。但是在某些情况下,需要在线程中获得其他线程set的值,就可以使用InheritableThreadLocal,从名字看出来这个就是用来继承的。

Thread类中存在两个变量:

ThreadLocal.ThreadLocalMap threadLocals = null;

ThreadLocal.ThreadLocalMap inheritableThreadLocals = null;

对于一个线程而言,threadLocals是给自己用的,而inheritableThreadLocals是给其子线程使用的。

查看new Thread()的源码:

private void init(ThreadGroup g, Runnable target, String name,
                      long stackSize, AccessControlContext acc) {
     ......
    if (parent.inheritableThreadLocals != null)
        this.inheritableThreadLocals =
            ThreadLocal.createInheritedMap(parent.inheritableThreadLocals);
        this.stackSize = stackSize;
    ......
    }

解释:线程A中新建一个子线程B,这时会判断线程A的inheritableThreadLocals的变量是否为null,如果不为空,就将线程A的inheritableThreadLocals变量赋给线程B的inheritableThreadLocals。

再看InheritableThreadLocal类的源码:

protected T childValue(T parentValue) {
        return parentValue;
    }
    ThreadLocalMap getMap(Thread t) {
       return t.inheritableThreadLocals;
    }
    void createMap(Thread t, T firstValue) {
        t.inheritableThreadLocals = new ThreadLocalMap(this, firstValue);
    }

其实和ThreadLocal中的方法差不多,起主要作用的是重写的getMap(Thread)方法,获得的是inheritableThreadLocals。

猜你喜欢

转载自blog.csdn.net/aimomo007/article/details/78855996