ThreadLocal与ThreadLocalMap

参考:理清ThreadLocal、ThreadLocalMap、Thread之间的关系 - 翎野君 - 博客园 (cnblogs.com)

img

ThreadLocalMapThreadLocal 类中的一个静态内部类,但它存在于每个线程的 Thread 对象内部,而不是 ThreadLocal 实例本身。

  • ThreadLocal:这是一个顶级类,用于定义线程局部变量。每个 ThreadLocal 实例表示一个特定类型的线程局部变量。
  • ThreadLocalMap:这是 ThreadLocal 类中的一个静态内部类,它提供了一种数据结构来存储每个线程的 ThreadLocal 实例及其对应的值。ThreadLocalMap 不是 ThreadLocal 的成员,而是存在于每个线程的内部。ThreadLocalMap中 key是ThreadLocal实例
  • 线程对象:每个 Thread 对象都有一个 ThreadLocalMap 成员变量(实际字段名为 threadLocals),用于存储该线程所有 ThreadLocal 实例的值。

当一个线程访问一个 ThreadLocal 变量时,ThreadLocalget() 方法会查找当前线程的 ThreadLocalMap,然后在这个 ThreadLocalMap 中查找与当前 ThreadLocal 实例相对应的值。同理,ThreadLocalset() 方法也会在当前线程的 ThreadLocalMap 中设置或更新一个值。

静态内部类的特点如下:

  1. 不依赖于外部类实例:与非静态内部类(也称为成员内部类)不同,静态内部类不需要外部类的实例即可创建。这意味着你可以直接通过外部类的名称来创建静态内部类的实例,而不需要先实例化外部类。

  2. 访问限制:静态内部类可以访问外部类的静态成员(包括静态变量和静态方法),但不能直接访问外部类的实例成员,除非你有一个外部类的实例。这是因为静态内部类没有隐含的对外部类实例的引用。

  3. 作用域和命名:静态内部类在语法上与顶级类相似,可以像顶级类那样自由地使用,而不会与外部类的实例产生任何联系。它有自己的作用域,可以有与外部类相同的成员名称而不会发生冲突。

  4. 实例化:静态内部类的实例化与顶级类类似,可以直接使用 new 关键字加上类名来创建。例如,如果你有一个名为 OuterClass 的类,其中包含一个静态内部类 InnerClass,你可以这样创建 InnerClass 的实例:

    Java深色版本

    1OuterClass.InnerClass innerInstance = new OuterClass.InnerClass();
    
  5. 静态变量和方法:静态内部类可以有静态成员,就像顶级类一样。这些静态成员同样可以在不实例化静态内部类的情况下访问。

  6. 继承与接口实现:静态内部类可以继承其他类或实现接口,与顶级类没有区别。

package org.example;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class ThreadLocalExample {

    // 创建一个 ThreadLocal 对象,它将存储 String 类型的数据
    private static final ThreadLocal<Integer> threadLocalData = new ThreadLocal<>();

    public static void main(String[] args) {
        ExecutorService executorService = Executors.newFixedThreadPool(2);

        // 提交第一个任务到线程池
        executorService.submit(() -> {
            if (threadLocalData.get() == null) {
                threadLocalData.set(0);
            }
            threadLocalData.set(threadLocalData.get() + 1);
            System.out.println("Thread 1: " + Thread.currentThread().getName());
            System.out.println("Thread 1 data: " + threadLocalData.get());
        });

        // 提交第二个任务到线程池
        executorService.submit(() -> {
            if (threadLocalData.get() == null) {
                threadLocalData.set(0);
            }
            threadLocalData.set(threadLocalData.get() + 1);
            System.out.println("Thread 2: " + Thread.currentThread().getName());
            System.out.println("Thread 2 data: " + threadLocalData.get());
        });

        // 关闭线程池
        executorService.shutdown();
    }
}

//输出为:
//Thread 1: pool-1-thread-1
//Thread 2: pool-1-thread-2
//Thread 1 data: 1
//Thread 2 data: 1

每个任务都会设置 threadLocalData 的值,并打印出当前线程的名字和线程局部变量的值。因为 ThreadLocal 保证了每个线程都有其独立的变量副本,所以即使多个线程共享同一个 ThreadLocal 实例,它们之间的变量值也是隔离的。

内存泄漏问题:
在这里插入图片描述
参考:【面试进阶之路】这次彻底说明白 ThreadLocal 内存泄漏问题_theallocal 内存泄露-CSDN博客

相关推荐

  1. ThreadLocal

    2024-07-11 16:36:06       48 阅读
  2. ThreadLocal

    2024-07-11 16:36:06       34 阅读
  3. threadLocal

    2024-07-11 16:36:06       20 阅读
  4. ThreadLocal介绍

    2024-07-11 16:36:06       38 阅读

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-07-11 16:36:06       67 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-07-11 16:36:06       72 阅读
  3. 在Django里面运行非项目文件

    2024-07-11 16:36:06       58 阅读
  4. Python语言-面向对象

    2024-07-11 16:36:06       69 阅读

热门阅读

  1. 软设之UML中的关系

    2024-07-11 16:36:06       19 阅读
  2. 编程语言在医疗健康领域的创新应用

    2024-07-11 16:36:06       20 阅读
  3. lvs三种模式

    2024-07-11 16:36:06       23 阅读
  4. 电商商城网站防护选购指南,高防CDN使用攻略

    2024-07-11 16:36:06       25 阅读
  5. [题解]P1113 杂务||拓扑排序板子题,但是dp求解

    2024-07-11 16:36:06       22 阅读
  6. PgMP考试报名攻略,不会的看这里!

    2024-07-11 16:36:06       24 阅读
  7. 高效利用iCloud指南

    2024-07-11 16:36:06       21 阅读
  8. 力扣面试经典150题

    2024-07-11 16:36:06       25 阅读
  9. MacOS 上安装和管理 Node.js

    2024-07-11 16:36:06       21 阅读
  10. C++ tcp中的可变长度结构体的序列化和反序列化

    2024-07-11 16:36:06       17 阅读