美文网首页程序员
java中ThreadLocal的简单理解

java中ThreadLocal的简单理解

作者: zpwd63 | 来源:发表于2018-09-05 12:58 被阅读0次

    ThreadLocal

    • 从JDK1.2版本开始提供了ThreadLocal类,以一种新的思路解决多线程并发问题。使用ThreadLocal实例维护多线程变量时,不会出现线程安全问题。虽然多个线程共用一个ThreadLocal实例,但在变量的使用上,各线程之间对变量不可见。

    ThreadLocal的使用

    ThreadLocal threadLocal = new ThreadLocal();
    
    
    • ThreadLocal提供无参的构造函数进行实例创建。在使用方面,该类也仅提供了几个简单的方法进行操作:

      1. set方法:threadLocal.set("threadLocal test")对ThreadLocal进行值得设置。
      2. get方法:Object test = threadLocal.get()进行值得获取。
      3. remove方法:threadLocal.remove();删除对应线程中存储的值。
    • 在JDK1.5版本开始,ThreadLocal提供泛型的支持,在获取值时不再需要需要进行类型强转。

    ThreadLocal<String> threadLocal = new ThreadLocal();
    threadLocal.set("threadLocal test");
    String test = threadLocal.get();
    
    

    源码浅析

    • 通过构造函数我们发现,ThreadLocal在构造函数中并没有做任何操作,所以我们从set方法作为入口进行分析。
    public void set(T value) {
      Thread t = Thread.currentThread();
      ThreadLocalMap map = getMap(t);
     if (map != null)
        map.set(this, value);
     else  
       createMap(t, value);
    }
    

    通过set方法我们可以看到,ThreadLocal实际是在其内部维护了一个ThreadLocalMap实例进行变量的存储,并把该实例与线程进行绑定。在ThreadLocalMap中key的值为this,也就是当前线程的ThreadLocal实例,value为当前设置的值

    • 在get方法中,通过调用ThreadLocalMap map = getMap(t);获取当前线程绑定的ThreadLocalMap实例,并获取value值。

    • 值得注意的是ThreadLocal同一线程只能存储一个值,如果需要存储多个值,可以考虑封装成一个对象进行存储。

    默认值

    • ThreadLocal通过protected T initialValue()方法进行value的初始化。
    protected T initialValue() {
        return null;
    }
    
    
    • 通过源码我们可以看到,该方法直接返回null。所以在创建实例后直接调用get方法时,我们得到的是空值。如果我们需要在ThreadLocal实例创建的时候进行初始化,可以通过继承ThreadLocal并重写initialValue()方法即可。
    • 那么initialValue()方法在何时进行调用的呢?通过查找源码我们在get方法中看到了该方法的调用。
    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(); 
    
    • 通过get方法执行流程可以看到,当ThreadLocal创建实例的时候,ThreadLocalMap map = getMap(t);返回的map值肯定为空,所以执行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;
    }
    
    • 从setInitialValue方法实现可以看到,在该方法中调用了initialValue返回了我们自定义的返回值,并设置到ThreadLocalMap实例中。

    • 通过上面的查看源码可以发现,ThreadLocal在设置初始化值时,需要在第一次调用get方法时才会进行初始化,而不是在实例创建的时候进行初始化。

    以上即为个人对ThreadLocal的简单理解。

    相关文章

      网友评论

        本文标题:java中ThreadLocal的简单理解

        本文链接:https://www.haomeiwen.com/subject/shlawftx.html