Wrayの知识库 Wrayの知识库
首页
  • Java 基础
  • Java 集合
  • Java 并发
  • Java IO
  • JVM
  • Spring Framework
  • Spring Boot
  • Spring Cloud
  • Spring Security
  • MySQL
  • Redis
  • MacOS
  • Linux
  • Windows
  • 纸质书
  • 电子书
  • 学习课程
疑难杂症
GitHub (opens new window)
首页
  • Java 基础
  • Java 集合
  • Java 并发
  • Java IO
  • JVM
  • Spring Framework
  • Spring Boot
  • Spring Cloud
  • Spring Security
  • MySQL
  • Redis
  • MacOS
  • Linux
  • Windows
  • 纸质书
  • 电子书
  • 学习课程
疑难杂症
GitHub (opens new window)
  • Java基础

    • Java概述
    • Java语法
    • 面向对象编程
    • Java数组
    • String字符串
    • 异常处理
  • Java集合

    • Java集合概述
    • ArrayList
    • LinkedList
    • HashMap
    • LinkedHashMap
    • HashSet
    • TreeMap
    • Queue&Deque
  • Java并发

    • Java并发概述
    • 线程与进程
    • Thread类与线程生命周期
    • 线程安全
    • synchronized关键字
    • volatile关键字
    • Java内存模型(JMM)
    • 线程间通信
    • 线程池
    • 并发工具类
    • 原子操作类Atomic
    • 并发锁
    • 并发容器
    • ConcurrentHashMap
    • BlockingQueue
    • CopyOnWriteArrayList
    • ThreadLocal
      • 1. ThreadLocal 的基本概念
      • 2. ThreadLocal 的常用方法
      • 3. ThreadLocal 的应用场景
      • 4. ThreadLocal 的实现原理与源码分析
        • 4.1 set 方法源码分析
        • 4.2 get 方法源码分析
      • 5. ThreadLocal 的内存泄漏问题
      • 6. 总结
    • Fork/Join框架
    • ScheduledThreadPoolExecutor
    • CompletableFuture
  • Java IO

    • Java IO概述
  • JVM

    • JVM概述
  • Java
  • Java并发
Wray
2024-10-31
目录

ThreadLocal

ThreadLocal 是 Java 并发编程中的一个工具类,主要用于为每个线程提供独立的变量副本,从而避免多线程之间对共享变量的竞争。它是实现线程隔离的重要工具,非常适合在多线程环境中处理不需要共享的状态。

# 1. ThreadLocal 的基本概念

  • 线程隔离:ThreadLocal 为每个线程提供了独立的变量副本,每个线程对变量的修改都不会影响其他线程,这样可以避免线程之间的数据共享和竞争问题。
  • 典型用法:常用于保存线程上下文信息,如用户会话、数据库连接等,确保每个线程都有独立的数据副本,避免相互干扰。

# 2. ThreadLocal 的常用方法

  • set(T value):将当前线程的副本设置为指定值。
  • get():获取当前线程对应的副本值。如果当前线程没有设置值,则会返回初始值。
  • remove():移除当前线程对应的值,防止内存泄漏。
  • initialValue():返回当前线程初始的变量副本,默认返回 null,可以通过重写该方法来提供默认值。

示例代码:

public class ThreadLocalExample {
    private static ThreadLocal<Integer> threadLocalValue = ThreadLocal.withInitial(() -> 1);

    public static void main(String[] args) {
        Runnable task = () -> {
            Integer value = threadLocalValue.get();
            System.out.println(Thread.currentThread().getName() + " initial value: " + value);
            threadLocalValue.set(value + 1);
            System.out.println(Thread.currentThread().getName() + " updated value: " + threadLocalValue.get());
        };

        Thread thread1 = new Thread(task);
        Thread thread2 = new Thread(task);

        thread1.start();
        thread2.start();
    }
}

在这个例子中,每个线程都有自己的 threadLocalValue 副本,线程之间互不影响。

# 3. ThreadLocal 的应用场景

  • 数据库连接管理:在每个线程中使用独立的数据库连接,避免多线程共享连接引发的安全问题。
  • 用户会话管理:在 Web 应用中,ThreadLocal 可以用于存储用户的会话信息,使得每个请求处理线程都有独立的用户信息。
  • 事务管理:在分布式事务处理过程中,ThreadLocal 可以用于保存事务上下文,确保同一线程中的操作使用相同的事务信息。

# 4. ThreadLocal 的实现原理与源码分析

  • ThreadLocalMap:ThreadLocal 的实现依赖于 ThreadLocalMap,它是一个特殊的哈希表,存储在每个线程内部,保证了线程的独立性。
  • 内部数据结构:每个线程内部都维护了一个 ThreadLocalMap,该 Map 使用 ThreadLocal 对象作为键,线程私有的变量作为值。

# 4.1 set 方法源码分析

  • set(T value) 方法:将值与当前线程关联。
    public void set(T value) {
        Thread t = Thread.currentThread();
        ThreadLocalMap map = getMap(t);
        if (map != null)
            map.set(this, value);
        else
            createMap(t, value);
    }
    
    • getMap(Thread t):获取当前线程的 ThreadLocalMap。
    • createMap(Thread t, T firstValue):如果当前线程没有 ThreadLocalMap,则为该线程创建一个新的 ThreadLocalMap。

# 4.2 get 方法源码分析

  • get() 方法:用于获取当前线程的变量副本。
    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();
    }
    
    • 如果当前线程的 ThreadLocalMap 中存在该 ThreadLocal 对应的值,则直接返回,否则调用 setInitialValue() 方法设置初始值。

# 5. ThreadLocal 的内存泄漏问题

  • 原因:ThreadLocalMap 的键是 ThreadLocal 对象的弱引用,值是强引用。如果 ThreadLocal 没有外部引用,GC 会回收键,但值不会被回收,从而导致内存泄漏。
  • 解决方案:在使用完 ThreadLocal 后,调用 remove() 方法显式地移除当前线程的变量副本,以避免内存泄漏。

# 6. 总结

ThreadLocal 是 Java 并发编程中实现线程隔离的重要工具,通过为每个线程提供独立的变量副本,可以避免线程间的竞争问题,简化多线程编程中的状态管理。ThreadLocal 常用于存储线程上下文信息,如数据库连接、用户会话、事务管理等。在使用 ThreadLocal 时,需要注意其潜在的内存泄漏风险,及时调用 remove() 方法以释放不再使用的资源。理解 ThreadLocal 的实现原理,有助于在多线程环境中编写更加高效、安全的代码。

上次更新: 2024/11/01, 13:45:14
CopyOnWriteArrayList
Fork/Join框架

← CopyOnWriteArrayList Fork/Join框架→

Copyright © 2023-2024 Wray | 鄂ICP备2024050235号-1
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式