多线程--ThreadLocal

目录

1.ThreadLocal原理

2.ThreadLocal源码分析

3.ThreadLocal用途及适用场景

4.总结


1.ThreadLocal原理

ThreadLocal叫做线程本地存储,它为变量在每个线程中都创建一个副本,那么每个线程可以访问自己内部的副本变量。在多线程中,ThreadLocal可以令线程在访问变量时具有隔离性,保证数据在线程间的安全性。

2.ThreadLocal源码分析

(1)读取实例

 public T get() {
     //获取当前线程
     Thread t = Thread.currentThread();
     //获取一个类型为ThreadLocalMap的map
     ThreadLocalMap map = getMap(t);
     //当map不为null时,获取ThreadLocal中变量的值
     if (map != null) {
        ThreadLocalMap.Entry e = map.getEntry(this);
        if (e != null) {
           @SuppressWarnings("unchecked")
           T result = (T)e.value;
           return result;
         }
      }
      //当map为null时,对变量进行初始化
      return setInitialValue();
  }

(2)设置初始值

private T setInitialValue() {
    //初始化一个值
    T value = initialValue();
    Thread t = Thread.currentThread();
    ThreadLocalMap map = getMap(t);
    if (map != null)
        map.set(this, value);
    else
        //如果map为null,创建一个键值对为当前线程和初始化值的map
        createMap(t, value);
    return value;
}

(3)设置实例

public void set(T value) {
    Thread t = Thread.currentThread();
    ThreadLocalMap map = getMap(t);
    if (map != null)
        map.set(this, value);
    else
        //如果map为null,创建一个键值对为当前线程和对应值的map
        createMap(t, value);
}

3.ThreadLocal用途及适用场景

(1)适用于两种场景:每个线程都需要有自己单独的实例;实例中需要在多个方法中共享,但不希望被多线程中共享。

(2)常见的用途:解决数据库连接和Session管理等。

4.总结

(1)ThreadLocal并不解决线程间共享数据的问题。

(2)ThreadLocal通过隐式的在不同线程内创建独立实例副本,避免了实例线程安全的问题。

(3)每个线程持有一个map并维护了ThreadLocal对象与具体实例的映射,该map由于只被持有它的线程访问,故不存在线程安全及锁的问题。

(4)ThreadLocalMap的Entry对ThreadLocal的引用为弱引用,避免了ThreadLocal对象无法被回收的问题。

(5)ThreadLocalMap的set方法通过调用replaceStaleEntry方法回收键为null的Entry对象的值(即为具体实例)以及Entry对象本身从而防止内存泄漏。

(6)ThreadLocal适用于变量在线程间隔离且在方法间共享的场景。

你可能感兴趣的:(Java基础)