Java ThreadLocal和InheritableThreadLocal源码分析

目录

  • 1. 概述
  • 2. Thread
    • 2.1 Constructors
    • 2.2 init
  • 3. ThreadLocal
    • 3.1 set
    • 3.2 get
    • 3.3 remove
  • 4. InheritableThreadLocal
  • 5. 总结

1. 概述

在上一篇Java ThreadLocalMap 源码解析的基础上,本文开始分析ThreadLocal相关源码。
参照下方UML图,可以看出:
1)Thread类关联ThreadLocalMap对象,分别对应成员变量threadLocals和inheritableThreadLocals;
2)ThreadLocal依赖Thread对象,主要表现为操作Thread对象的ThreadLocalMap对象;
3)InheritableThreadLocal类继承ThreadLocal类,主要用于实现子线程继承父线程的ThreadLocalMap对象inheritableThreadLocals。
Java ThreadLocal和InheritableThreadLocal源码分析_第1张图片

2. Thread

2.1 Constructors

如下源码,Thread的构造器方法全部调用了init方法。其中第三个构造器最后一个参数false表示不继承父线程的ThreadLocalMap对象,其余构造器全部默认继承父线程的ThreadLocalMap对象。

    public Thread() {
        init(null, null, "Thread-" + nextThreadNum(), 0);
    }
    public Thread(Runnable target) {
        init(null, target, "Thread-" + nextThreadNum(), 0);
    }    
    Thread(Runnable target, AccessControlContext acc) {
        init(null, target, "Thread-" + nextThreadNum(), 0, acc, false);
    }
    public Thread(ThreadGroup group, Runnable target) {
        init(group, target, "Thread-" + nextThreadNum(), 0);
    }
    public Thread(String name) {
        init(null, null, name, 0);
    }
    public Thread(ThreadGroup group, String name) {
        init(group, null, name, 0);
    }
    public Thread(Runnable target, String name) {
        init(null, target, name, 0);
    }
    public Thread(ThreadGroup group, Runnable target, String name) {
        init(group, target, name, 0);
    }
    public Thread(ThreadGroup group, Runnable target, String name,
                  long stackSize) {
        init(group, target, name, stackSize);
    }

2.2 init

    /* ThreadLocal values pertaining to this thread. This map is maintained
     * by the ThreadLocal class. */
    ThreadLocal.ThreadLocalMap threadLocals = null;

    /*
     * InheritableThreadLocal values pertaining to this thread. This map is
     * maintained by the InheritableThreadLocal class.
     */
    ThreadLocal.ThreadLocalMap inheritableThreadLocals = null;
    
    private void init(ThreadGroup g, Runnable target, String name,
                      long stackSize) {
        init(g, target, name, stackSize, null, true);
    }
    private void init(ThreadGroup g, Runnable target, String name,
                      long stackSize, AccessControlContext acc,
                      boolean inheritThreadLocals) {
		/*** 为了强调本文描述重点,此处省略部分代码 ***/
        if (inheritThreadLocals && 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();
    }

结合上述代码,当一个线程创建后,成员变量threadLocals为空,成员变量inheritableThreadLocals则根据是否继承父线程inheritableThreadLocals判断逻辑初始化。

3. ThreadLocal

ThreadLocalMap类是ThreadLocal类的内部静态类。分析完ThreadLocalMap源码后,再分析ThreadLocal源码,就简单许多了。

3.1 set

set方法的作用是将传参设置到当前线程的成员变量threadLocals中。如果成员变量threadLocals为空,则调用creaeMap方法新建。

    public void set(T value) {
        Thread t = Thread.currentThread();
        ThreadLocalMap map = getMap(t);
        if (map != null)
            map.set(this, value);
        else
            createMap(t, value);
    }
    void createMap(Thread t, T firstValue) {
        t.threadLocals = new ThreadLocalMap(this, firstValue);
    }

3.2 get

get方法从当前线程的成员变量threadLocals中获取当前ThreadLocal作为Key对应Entry的Value,如果threadLocals为空,或未找到,则返回初始值(可重写,默认为空)。

    public T get() {
        Thread t = Thread.currentThread();
        ThreadLocalMap map = getMap(t);
        if (map != null) {
            ThreadLocalMap.Entry e = map.getEntry(this);
            if (e != null) {
                @SuppressWarnings("unchecked")
                T result = (T)e.value;
                return result;
            }
        }
        return setInitialValue();
    }
    private T setInitialValue() {
        T value = initialValue();
        Thread t = Thread.currentThread();
        ThreadLocalMap map = getMap(t);
        if (map != null)
            map.set(this, value);
        else
            createMap(t, value);
        return value;
    }
    protected T initialValue() {
        return null;
    }

3.3 remove

从当前线程成员变量threadLocals中删除当前ThreadLocal作为Key对应Entry。

     public void remove() {
         ThreadLocalMap m = getMap(Thread.currentThread());
         if (m != null)
             m.remove(this);
     }

4. InheritableThreadLocal

public class InheritableThreadLocal extends ThreadLocal {
 
    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);
    }
}

InheritableThreadLocal类继承ThreadLocal类。需要强调的是,childValue方法用于继承父线程inheritableThreadLocals时,以什么形式复制其中的值,默认为直接返回父线程inheritableThreadLocals中Entry的Value值。

5. 总结

结合以上分析,ThreadLocal和InheritableThreadLocal主要用于变量在线程间共享,并不能解决线程安全问题,原因是其变量共享方式为潜拷贝。

你可能感兴趣的:(Java)