概述

ThreadLocal 是 Java 中一个用于提供线程局部变量的工具类。它为每个线程提供了一个独立的副本,使得每个线程在使用变量时不会受到其他线程的干扰。在多线程环境下,使用 ThreadLocal 可以保证变量的线程安全性。本文将从源码角度解析 ThreadLocal 的实现原理。

ThreadLocal 的内部结构和关键方法

ThreadLocal 类的内部结构包括一个内部类 ThreadLocalMap 和一个继承自 WeakReference 的静态内部类 ThreadLocalMap.ThreadLocalMap 是 ThreadLocal 的关键部分,它是一个线程局部变量的容器,通过 ThreadLocalMap 来存储每个线程的独立副本。ThreadLocalMap 的实现依赖于 ThreadLocal 的哈希值,因此 ThreadLocal 的哈希值对于线程局部变量的访问起到了重要的作用。

ThreadLocal 类的关键方法包括:

  1. set() 方法:用来设置当前线程的线程局部变量的值。
  2. get() 方法:用来获取当前线程的线程局部变量的值。
  3. remove() 方法:用来移除当前线程的线程局部变量的值。
  4. initialValue() 方法:用来初始化当前线程的线程局部变量的默认值。
  5. createMap() 方法:用来创建当前线程的 ThreadLocalMap 对象。
  6. getMap() 方法:用来获取当前线程的 ThreadLocalMap 对象。

ThreadLocal 的实现原理

ThreadLocal 的实现原理主要涉及了哈希值的计算和 ThreadLocalMap 的操作。当一个线程首次调用 ThreadLocal 的 set() 或 get() 方法时,会先获取当前线程的 ThreadLocalMap 对象,如果 ThreadLocalMap 对象不存在,则会通过 createMap() 方法来创建。然后,通过 ThreadLocal 的哈希值,确定线程局部变量在 ThreadLocalMap 中的存储位置。如果当前线程的 ThreadLocal 对象已经存在于 ThreadLocalMap 中,则直接进行存取操作;否则,通过 ThreadLocal 的 set() 方法将线程局部变量存储到 ThreadLocalMap 中。对于已经存在于 ThreadLocalMap 中的 ThreadLocal 对象,可以通过 get() 方法来获取对应的线程局部变量的值。

需要注意的是,ThreadLocalMap 中的 Entry 是通过 ThreadLocal 的弱引用来引用的。这是为了避免内存泄漏,当 ThreadLocal 没有被其他对象引用时,垃圾回收器会自动回收 ThreadLocal 对象,从而避免了对线程局部变量的强引用。


/**
 * ThreadLocal的set()方法
 * 将当前线程的线程局部变量设置为指定的值。
 */
public void set(T value) {
    // 获取当前线程的ThreadLocalMap
    Thread t = Thread.currentThread();
    ThreadLocalMap map = getMap(t);
    if (map != null)
        map.set(this, value);
    else
        createMap(t, value);
}

/**
 * ThreadLocalMap的set()方法
 * 将指定的ThreadLocal对象映射到指定的值。
 */
private void set(ThreadLocal key, Object value) {
    // 计算ThreadLocal对象的哈希值
    int i = key.threadLocalHashCode & (table.length - 1);
    // 遍历哈希桶,查找是否存在相同的ThreadLocal对象
    for (Entry e = table[i]; e != null; e = e.next) {
        ThreadLocal k = e.get();
        if (k == key) {
            // 更新相同ThreadLocal对象的值
            e.value = value;
            return;
        }
    }
    // 创建新的Entry并插入到对应的哈希桶中
    addEntry(key, value, i);
}
Java

以上是 ThreadLocal 类和 ThreadLocalMap 类中的部分关键代码,从中可以看出 ThreadLocal 的实现原理。通过 ThreadLocal 的 set() 方法将线程局部变量设置为指定值时,会先获取当前线程的 ThreadLocalMap 对象,然后通过 ThreadLocal 的哈希值确定线程局部变量在 ThreadLocalMap 中的位置。如果 ThreadLocal 对象已经存在于 ThreadLocalMap 中,则直接更新线程局部变量的值;否则,创建新的 Entry 并插入到哈希桶中。通过 ThreadLocal 的 get() 方法可以获取线程局部变量的值。