🔔简介
ThreadLocal 是 Java 提供的一个线程内部的存储类,可以在指定的线程中存储数据,数据存储以后,只有在指定线程中可以获取到存储的数据,对于其他线程来说则无法获取到数据。
🔔特点
- ThreadLocal 中存储的是线程隔离的数据,该数据只能被当前线程访问,其他线程无法访问和修改。
- 每个 ThreadLocal 对象只能被当前线程使用,其他线程无法访问。
- 每个线程中都可以独立地改变自己的 ThreadLocal 变量,不会影响其他线程的变量。
- 当线程结束时,ThreadLocal 中存储的对象会被垃圾回收。
🔔实现原理
- ThreadLocal 是一个映射表,Key 是 ThreadLocal 实例本身,Value 是真正要存储的对象。每个线程都有一个独立的 ThreadLocalMap 副本。
- 每个 Thread 线程内部都有一个 ThreadLocalMap 的引用,这个映射表是用于存储实际的对象或值的。
- 当调用 ThreadLocal 的 set() 方法设置值的时候,先得到当前线程的 ThreadLocalMap,然后将 ThreadLocal 实例本身作为键,而要存储的对象作为值放入 ThreadLocalMap。
- 当调用 get() 方法获取值时,同样先获取当前线程的 ThreadLocalMap,然后以 ThreadLocal 实例作为键,从 ThreadLocalMap 获取对应的对象。
- 因为每个线程的 ThreadLocalMap 是隔离的,所以一个线程无法访问其他线程中的值,从而实现了线程隔离。
- 当线程结束时,线程的 ThreadLocalMap 也会随之销毁,避免了内存泄漏。
- ThreadLocalMap 使用 ThreadLocal 的弱引用作为 key,如果一个 ThreadLocal 没有外部强引用来引用它,那么系统 GC 的时候,这个 ThreadLocal 会被回收,这样就避免了 ThreadLocal 本身的内存泄漏。
🔔使用场景
- 频繁创建和销毁的对象,可以避免创建开销。
- 每个线程需要单独的实例,通常用于代理,事务等。
- 需要将共享资源的访问限制在同一个线程内,避免多线程访问导致竞争。
- 存储线程上下文数据,如用户身份信息等。
🔔内存泄露可能原因
- 孤儿引用对象无法被GCThreadLocalMap使用ThreadLocal的弱引用作为key,如果一个ThreadLocal没有外部强引用引用它,那么系统GC的时候,这个ThreadLocal势必会被回收,而它对应的value却有可能无法被回收,因为当前线程的ThreadLocalMap还持有该value的强引用,导致value无法被回收,出现内存泄漏。
- 线程生命周期过长如果线程生命周期过长,那么这些线程持有的ThreadLocalMap也不会被回收,即使ThreadLocal已经被回收,但ThreadLocalMap还在,value也无法被回收。这种情况下可能需要手动调用remove()方法清除数据。
🔔解决内存泄露方法
- 每次使用完ThreadLocal,都调用它的remove()方法,清除数据值。
- 使用完线程后,确保线程销毁,不要使线程生命周期过长。
- 不需要维护的ThreadLocal及时设置为null,让它可被回收。
- 用try-finally块包装线程执行体,在finally块中清除ThreadLocal。
🔔示例
public class ThreadLocalExample {
// 声明ThreadLocal变量
private static final ThreadLocal<String> threadLocal = new ThreadLocal<>();
public static void main(String[] args) {
// 在主线程中设置threadLocal的值
threadLocal.set("Main Thread");
// 在子线程中获取和设置threadLocal的值
new Thread(() -> {
System.out.println(threadLocal.get()); // 输出null
threadLocal.set("Child Thread");
System.out.println(threadLocal.get()); // 输出Child Thread
}).start();
// 在主线程中再次打印threadLocal的值
System.out.println(threadLocal.get()); // 输出Main Thread
}
}
🔔写在最后
如果大家对相关文章感兴趣,可以关注公众号"架构殿堂",会持续更新AIGC,java基础面试题, netty, spring boot,spring cloud等系列文章,一系列干货随时送达!