ThreadLocal源码分析(一)
创始人
2025-05-31 13:30:52

一、什么是ThreadLocal


ThreadLocal是Java中一个线程级别的变量,它可以让每个线程都拥有自己单独的变量副本,实现了线程间数据的隔离。ThreadLocal提供了一种创建线程局部变量的方式,每个线程都可以独立地改变自己的副本,而不会影响其他线程的副本。ThreadLocal通常用于在多线程环境下保存线程私有的数据,例如用户身份信息、数据库连接、Session对象等。通过ThreadLocal可以避免线程之间的数据共享问题,提高程序的性能和安全性。

二、ThreadLocal作用


ThreadLocal的作用如下:

  1. 提供线程局部变量:ThreadLocal提供了一种创建线程局部变量的方式,每个线程都可以独立地改变自己的副本,而不会影响其他线程的副本。

  1. 隔离线程之间的数据:ThreadLocal可以隔离线程之间的数据,每个线程都可以有自己的副本,这样就避免了线程之间的数据共享问题。

  1. 提高程序性能:ThreadLocal可以提高程序的性能,因为每个线程都可以直接访问自己的副本,不必竞争共享变量,避免了线程间的锁竞争问题。

  1. 管理共享变量的访问:ThreadLocal可以管理共享变量的访问,每个线程都可以通过ThreadLocal对象访问共享变量,而不必担心线程安全问题。ThreadLocal的作用就是提供一种线程安全的方式,管理共享变量的访问,隔离线程之间的数据,提高程序性能。

三、ThreadLocal 使用方式


1、创建ThreadLocal对象

private static final ThreadLocal USER_INFO_LOCAL = new ThreadLocal();

2、设置值

public static void setLoginUserVO(UserInfo loginUserVO) {USER_INFO_LOCAL.set(loginUserVO);
}

3、获取值

public static UserInfo getLoginUserVO() {return (UserInfo)USER_INFO_LOCAL.get();
}

4、删除数据

public static void clear() {USER_INFO_LOCAL.remove();
}

需要注意,ThreadLocal一般用于解决多线程环境下共享变量的问题,但也容易引发内存泄露问题,因此在使用完后需要及时清理ThreadLocal中的数据。

四、源码分析


4.1 Diagrams

4.2 属性

// ThreadLocal实例的唯一标识符,是通过nextHashCode()方法生成的,它保证了ThreadLocal实例之间的唯一性和线程安全性。
private final int threadLocalHashCode = nextHashCode();// 是ThreadLocal类中nextHashCode()方法中生成哈希值的一个增量,它是一个常数,用于降低哈希冲突,保证哈希表的性能和线程安全性。
private static final int HASH_INCREMENT = 0x61c88647;
// nextHashCode是一个AtomicInteger类型的变量,用于生成ThreadLocal实例的哈希码
private static AtomicInteger nextHashCode = new AtomicInteger();

.3 构造函数

// 无参构造函数
public ThreadLocal() {
}

ThreadLocal类的构造函数不接受任何参数,主要是每个ThreadLocal实例都是与特定线程相关,而不是特定的数据类型相关联的。因此,每个ThreadLocal实例可以存储任何类型的值,而不需要指定类型。这也是ThreadLocal类的一个重要特点,它提供了一种通用的、线程安全的机制来存储每个线程的数据,避免了多线程环境中共享变量的问题。

因此,public ThreadLocal()的含义是ThreadLocal类的构造方法,用于创建一个新的ThreadLocal实例,并初始化为默认值null。在使用ThreadLocal实例时,需要使用set方法为其设置一个初始值。

4.4 方法

4.4.1 set(T value)方法

用于为当前线程中ThreadLocal对象设置值。

  1. 获取当前线程;

  1. 根据当前线程获取对应的ThreadLocalMap对象。

  1. 如果ThreadLocalMap对象存在,则使用set方法将ThreadLocal对象和值保存到ThreadLocalMap对象中。

  1. 如果ThreadLocalMap对象不存在,说明当前线程还没有ThreadLocalMap对象,此时需要使用createMap方法为其创建一个ThreadLocalMap对象,并将ThreadLocal对象和值保存到其中。

// 为当前线程中ThreadLocal对象设置值
public void set(T value) {// 获取当前线程Thread t = Thread.currentThread();// 根据当前线程获取对应的ThreadLocalMap对象。ThreadLocalMap map = getMap(t);// 如果ThreadLocalMap对象存在,使用set方法将ThreadLocal对象和值保存到ThreadLocalMap对象中。if (map != null)map.set(this, value);else//  如果ThreadLocalMap对象不存在,使用createMap方法为其创建一个ThreadLocalMap对象,并将ThreadLocal对象和值保存到其中。createMap(t, value);
}

4.4.2 get()方法

用于获取当前线程中ThreadLocal对象对应的值。

  1. 获取当前线程;

  1. 根据当前线程获取对应的ThreadLocalMap对象。

  1. 如果ThreadLocalMap对象存在,则从中获取ThreadLocal对象对应的Entry对象,

  1. 如果Entry对象存在,则返回其值,否则返回null。

  1. 如果ThreadLocalMap对象不存在,说明当前线程还没有ThreadLocalMap对象,此时需要使用setInitialValue方法来为其设置一个初始值,并返回该值。

// 如果没有获取到数据,则会初始一个数据,将线程当作key,null 当作value 放入ThreadLocalMap中
public T get() {// 获取当前线程。Thread t = Thread.currentThread();// 根据当前线程获取对应的ThreadLocalMap对象ThreadLocalMap map = getMap(t);// 如果ThreadLocalMap对象存在if (map != null) {// 从中获取ThreadLocal对象对应的Entry对象。ThreadLocalMap.Entry e = map.getEntry(this);// 如果Entry对象存在,则返回其值if (e != null) {@SuppressWarnings("unchecked")T result = (T)e.value;return result;}}// 如果ThreadLocalMap对象不存在,说明当前线程还没有ThreadLocalMap对象,此时需要使用setInitialValue方法来为其设置一个初始值,并返回该值。return setInitialValue();
}

4.4.3 setInitialValue()方法

用于为当前线程中ThreadLocal对象设置一个初始值。

  1. 调用initialValue方法获取初始值;

  1. 获取当前线程;

  1. 根据当前线程获取对应的ThreadLocalMap对象。

  1. 如果ThreadLocalMap对象存在,则使用set方法将ThreadLocal对象和初始值保存到ThreadLocalMap对象中。

  1. 如果ThreadLocalMap对象不存在,说明当前线程还没有ThreadLocalMap对象,此时需要使用createMap方法为其创建一个ThreadLocalMap对象,并将ThreadLocal对象和初始值保存到其中。

  1. 最后,返回设置的初始值。

// 初始值,key:当前线程,value:null
private T setInitialValue() {// 调用initialValue方法获取初始值;实际上是null T value = initialValue();// 获取当前线程Thread t = Thread.currentThread();// 根据当前线程获取对应的ThreadLocalMap对象ThreadLocalMap map = getMap(t);// 如果ThreadLocalMap对象存在,则使用set方法将ThreadLocal对象和初始值保存到ThreadLocalMap对象中if (map != null)map.set(this, value);else// 如果ThreadLocalMap对象不存在,说明当前线程还没有ThreadLocalMap对象,此时需要使用createMap方法为其创建一个ThreadLocalMap对象,并将ThreadLocal对象和初始值保存到其中。createMap(t, value);// 返回设置的初始值return value;
}

4.4.4 remove()方法

用于清除当前线程中ThreadLocal对象的值。

  1. 获取当前线程,然后根据当前线程获取对应的ThreadLocalMap对象。

  1. 如果ThreadLocalMap对象存在,则使用remove方法将ThreadLocal对象从ThreadLocalMap对象中移除。

  1. 如果ThreadLocalMap对象不存在,则说明当前线程中没有该ThreadLocal对象的值,因此无需进行任何操作。

public void remove() {// 获取当前线程,然后根据当前线程获取对应的ThreadLocalMap对象ThreadLocalMap m = getMap(Thread.currentThread());// 如果ThreadLocalMap对象存在if (m != null)// 则使用remove方法将ThreadLocal对象从ThreadLocalMap对象中移除。m.remove(this);
}

相关内容

热门资讯

初中作文爱让人感动【通用5篇... 初中作文爱让人感动 篇一爱的力量爱是一种伟大的力量,它能够让人产生无尽的感动。在我们的生活中,有很多...
无奈的我们初一作文【经典3篇... 无奈的我们初一作文 篇一初一是我们人生中的一个重要阶段,对于大部分同学来说,初一意味着从小学踏入初中...
曾经有一个人为题的作文【通用... 曾经有一个人为题的作文 篇一曾经有一个人从前有一个人,他的名字叫李明。他是一个普通的年轻人,过着平凡...
在山的那边作文【优秀3篇】 在山的那边作文 篇一静谧与自由我曾经听过一个故事,说的是在遥远的山的那边,有一个神秘的世界。这个世界...
ST明诚:预计2025年上半年... 每经AI快讯,ST明诚(SH 600136,收盘价:2元)7月11日晚间发布业绩预告,预计2025年...