Java并发编程ThreadLocal内部实现(四)|Java基础

190 阅读3分钟

这是我参与8月更文挑战的第8天,活动详情查看:8月更文挑战

概述

每个Thread维护一个ThreadLocalMap,这个Map的key是ThreadLocal实例对象本身,value才是真正要春初的值Object。

  • 每个ThreadLocal线程内部都有一个map(ThreadLocalMap)
  • Map里面存储ThradLocal对象(Key)和线程的变量副本(Value)
  • Thread内部的Map是由ThreadLocal维护的,由ThreadLocal负责向map获取和设置线程的变量值。
  • 对于不同的线程,每次获取副本值时,别的线程并不能获取到当前现场的副本值,形成了副本的隔离,互不干扰。 ThreadLocal内部方法以及内部类 image.png

内部的方法的实现

方法声明描述
ThreadLocal()创建ThreadLocal
public void set()设置当前线程绑定的变量
public T get()获取当前线程绑定的变量
public void remove()移除当前线程绑定的变量

ThreadLocal对外提供了四个方法,接下来一个个去分析。

1.set()

/**
 * 设置当前线程对于的ThreadLocal的值
 *
 * @parameter value 将要保存在当前线程对应的ThreadLocal的值
 */
public void set(T value) {
    //获取当前线程
    Thread t = Thread.currentThread();
    //获取当前线程对象中维护的ThradLocalMap对象
    ThreadLocalMap map = getMap(t);
    if (map != null)
        //set设置此实体的entry,以当前ThreadLocal为key
        map.set(this, value);
    else
        //1.当前线程,不存在ThreadLocalMap对象
        //2.调用createMap进行ThreadLocalMap对象的初始化
        //3.将当前线程和value作为第一个entry存放到ThreadLocalMap中
        createMap(t, value);
}

/**
 * 设置当前线程对应的ThreadLocalMap
 *
 * @parameter t 当前线程
 */
ThreadLocalMap getMap(Thread t) {
    return t.threadLocals;
}

/**
 * 创建当前线程所对应的ThreadLocalMap
 * Thread里所维护的threadLocals是在这里所进行的初始化
 *
 * @param t the current thread
 * @param firstValue 存放map中第一个entry的值
 */
void createMap(Thread t, T firstValue) {
    t.threadLocals = new ThreadLocalMap(this, firstValue);
}

image.png //Thread里各自维护了一个ThreadLocalMap的实例对象

set()执行流程

  1. 首先获取当前程序,并根据当前线程获取一个map
  2. 如果获取的Map不为空,则将参数设置到map。(ThreadLocal作为key)
  3. 如果map为空,则给该线程创建Map,并设置初始值,完成Thread里维护的ThreadLocalMap的初始化

2.get()

/**
 * 返回当前线程中保存的以ThreadLocal为key所对应的value
 * 如果没有此Key,通过调用SuppliedThreadLocal.initialValue()进行初始化
 */
public T get() {
    //获取当前线程
    Thread t = Thread.currentThread();
    //获取当前线程维护的ThradLocalMap
    ThreadLocalMap map = getMap(t);
    if (map != null) {
        //以当前ThradLocal作为key,调用getEntry获取存储实体
        ThreadLocalMap.Entry e = map.getEntry(this);
        if (e != null) {
            @SuppressWarnings("unchecked")
            //get value
            T result = (T)e.value;
            return result;
        }
    }
    // map不存在或者map存在但是没有与 当前ThreadLocal关联的entry
    // 初始化map
    return setInitialValue();
}
/**
 * 初始化ThreadLocalMap
 */
private T setInitialValue() {
    //获取初始化的值,可被子类重写,如果不重写的话默认返回null
    T value = initialValue();
    Thread t = Thread.currentThread();
    ThreadLocalMap map = getMap(t);
    if (map != null)
        map.set(this, value);
    else
        createMap(t, value);
    return value;
}

get()执行流程

  1. 获取当前线程的ThreadLocalMap
  2. map != null? 获取map中对于的Entry : initialValue()获取初始值,然后初始化map
  3. 如果map.getEntry(this)不为null,返回value