以下是 ThreadLocal 类方法源码解析:


1. get():获取当前线程的 ThreadLocal 变量的值。如果变量尚未被当前线程设置,则返回 null。

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();
}

解释:该方法首先获取当前线程 Thread.currentThread()

然后,调用 getMap(t) 方法获取当前线程的 ThreadLocalMap 对象 map

如果 map 不为 null,表示当前线程已经有一个 ThreadLocalMap,可以尝试获取与当前 ThreadLocal 对象关联的值。

调用 map.getEntry(this) 方法,传入当前 ThreadLocal 对象作为参数,获取与之关联的 Entry 节点 e

如果 e 不为 null,表示找到了与当前 ThreadLocal 对象关联的值。通过强制类型转换将 e.value 转换为泛型类型 T,并将其赋值给 result 变量。

最后,返回 result,即当前线程中与当前 ThreadLocal 对象关联的值。

如果 mapnull 或者未找到与当前 ThreadLocal 对象关联的值,则调用 setInitialValue() 方法来设置初始值,并返回该值。

总之,get() 方法用于获取当前线程中与当前 ThreadLocal 对象关联的值。它首先获取当前线程的 ThreadLocalMap 对象,然后在该对象中查找与当前 ThreadLocal 对象关联的值。如果找到了值,则返回该值;否则,设置初始值并返回。


2. 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;
}

以下是该方法的具体步骤:

  1. 调用 initialValue() 方法获取线程本地变量的初始值,将其赋给变量 value
  2. 获取当前线程 Thread.currentThread()
  3. 调用 getMap(Thread t) 方法获取当前线程对应的 ThreadLocalMap 对象,并将其赋给变量 map
  4. 检查 map 是否为 null。如果不为 null,表示当前线程已经有一个 ThreadLocalMap 对象,可以直接调用 map.set(this, value) 方法将当前 ThreadLocal 对象和对应的值存入 map 中。
  5. 如果 mapnull,表示当前线程还没有 ThreadLocalMap 对象,调用 createMap(t, value) 方法创建一个新的 ThreadLocalMap 对象,并将当前 ThreadLocal 对象和对应的值存入新创建的 map 中。
  6. 返回 value,即线程本地变量的初始值。

这个方法的作用是在首次访问线程本地变量时,为其设置初始值,并将其与当前线程关联起来。如果当前线程已经有一个 ThreadLocalMap 对象,则直接存入对应的键值对;如果当前线程还没有 ThreadLocalMap 对象,则创建一个新的 ThreadLocalMap 对象,并将键值对存入其中。

需要注意的是,setInitialValue() 方法是作为 ThreadLocal 类的内部方法使用的,在我们使用 ThreadLocal 类时并不需要直接调用它。


3. set(T value):该方法用于将指定的值 value 关联到当前线程中的当前 ThreadLocal 对象。

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

解释:该方法首先获取当前线程 Thread.currentThread()

然后,调用 getMap(t) 方法获取当前线程的 ThreadLocalMap 对象 map

如果 map 不为 null,表示当前线程已经有一个 ThreadLocalMap,可以直接调用 map.set(this, value) 方法将当前 ThreadLocal 对象和指定的值 value 关联起来。

如果 mapnull,表示当前线程还没有 ThreadLocalMap,需要调用 createMap(t, value) 方法来创建一个新的 ThreadLocalMap 并将其与当前线程关联起来。

总之,set(T value) 方法用于将指定的值关联到当前线程中的当前 ThreadLocal 对象。它首先获取当前线程的 ThreadLocalMap 对象,然后根据是否存在该对象来选择直接设置值或创建新的 ThreadLocalMap 对象。


4. remove():该方法用于从当前线程的 ThreadLocalMap 中移除与当前 ThreadLocal 对象关联的值。

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

解释:该方法首先通过调用 getMap(Thread.currentThread()) 方法获取当前线程的 ThreadLocalMap 对象 m

如果 m 不为 null,表示当前线程有一个 ThreadLocalMap 对象,可以调用 m.remove(this) 方法来移除与当前 ThreadLocal 对象关联的值。

如果 mnull,表示当前线程没有 ThreadLocalMap 对象,无需进行任何操作。

总之,remove() 方法用于从当前线程的 ThreadLocalMap 中移除与当前 ThreadLocal 对象关联的值。它首先获取当前线程的 ThreadLocalMap 对象,然后根据是否存在该对象来选择是否进行移除操作。


5. initialValue():该方法用于提供一个初始值,以便在首次访问 ThreadLocal 对象时使用。

protected T initialValue() {
    return supplier.get();
}

解释:该方法调用了一个 supplier.get() 方法来获取初始值。这里的 supplier 是一个 Supplier<T> 类型的对象,它提供了一个无参数的 get() 方法,用于获取初始值。

通过重写 initialValue() 方法,我们可以自定义初始值的生成逻辑。默认情况下,如果没有手动设置初始值,ThreadLocal 的初始值为 null

总之,initialValue() 方法用于提供一个初始值,在首次访问 ThreadLocal 对象时使用。通过重写该方法,我们可以自定义初始值的生成逻辑。


6. withInitial(Supplier<? extends T> supplier):该方法用于创建一个具有初始值供应者的 ThreadLocal 对象。

public static <S> ThreadLocal<S> withInitial(Supplier<? extends S> supplier) {
    return new SuppliedThreadLocal<>(supplier);
}

解释:该方法使用提供的 Supplier 对象来创建一个 SuppliedThreadLocal 对象,该对象实现了 ThreadLocal 接口。Supplier 是一个函数式接口,它定义了一个无参数的 get() 方法,用于获取初始值。

通过调用 withInitial(supplier) 方法,我们可以创建一个具有初始值供应者的 ThreadLocal 对象。该供应者将在首次访问 ThreadLocal 对象时生成初始值。

总之,withInitial(Supplier<? extends S> supplier) 方法用于创建一个具有初始值供应者的 ThreadLocal 对象。通过该方法,我们可以方便地指定一个供应者来生成初始值。


7. getMap(Thread t) :该方法用于获取给定线程 t 对应的 ThreadLocalMap 对象。

ThreadLocalMap getMap(Thread t) {
    return t.threadLocals;
}

解释:在 ThreadLocal 类中,每个线程都有一个名为 threadLocals 的字段,它是一个 ThreadLocalMap 对象。该字段用于存储线程本地变量的键值对。

getMap(Thread t) 方法中,通过访问线程 tthreadLocals 字段,直接返回对应的 ThreadLocalMap 对象。

这个方法的作用是为了获取特定线程的 ThreadLocalMap 对象,以便进行后续的操作,比如获取或设置线程本地变量的值。

需要注意的是,getMap(Thread t) 方法是 ThreadLocal 类的内部方法,我们通常不需要直接调用它,而是通过 ThreadLocal 对象的方法间接地访问线程本地变量。


8. createMap(Thread t, T firstValue):该方法用于在当前线程中创建一个新的 ThreadLocalMap 对象,并将初始值与当前 ThreadLocal 对象关联起来。

void createMap(Thread t, T firstValue) {
    t.threadLocals = new ThreadLocalMap(this, firstValue);
}

以下是该方法的具体步骤:

  1. 接收一个线程对象 t 和一个初始值 firstValue 作为参数。
  2. 创建一个新的 ThreadLocalMap 对象,并将当前 ThreadLocal 对象和初始值作为参数传递给构造函数。
  3. 将新创建的 ThreadLocalMap 对象赋值给当前线程的 threadLocals 字段,即将其与当前线程关联起来。

这个方法的作用是在当前线程中创建一个新的 ThreadLocalMap 对象,并将初始值与当前 ThreadLocal 对象关联起来。ThreadLocalMap 对象用于存储线程本地变量的键值对。通过将新创建的 ThreadLocalMap 对象赋值给当前线程的 threadLocals 字段,就可以在当前线程中使用 ThreadLocal 对象来获取和设置线程本地变量的值。


以上是 ThreadLocal 类常用方法的源码和详细解释。这些方法允许您在多线程环境中维护线程本地变量,并提供了获取、设置、移除 ThreadLocal 变量的功能。


今夜有点儿凉
40 声望3 粉丝

今夜有点儿凉,乌云遮住了月亮。