美文网首页程序员
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