• Java面试题:请谈谈对ThreadLocal的理解?


    ThreadLocal是一种特殊的变量存储机制,它提供了一种方式,可以在每个线程中保存数据,而不会受到其他线程的影响。这种机制在多线程编程中非常有用,因为它允许每个线程拥有自己的数据副本,从而避免了数据竞争和线程之间的干扰,以空间换时间。

    在Java中,ThreadLocal的实现主要涉及到三个类:ThreadLocal、ThreadLocalMap和WeakReference。ThreadLocal类是核心类,用于保存线程局部变量,并提供相应的访问方法。ThreadLocalMap是一个哈希表,用于存储每个线程的本地变量。WeakReference类是一个辅助类,用于处理弱引用问题。

    下图可以增强理解:

     

    由上图我们可以看到ThreadLocal的内部实现包括以下几个步骤:

    • 创建一个ThreadLocalMap对象,用于存储每个线程的本地变量。

    • 在ThreadLocal对象中保存一个WeakReference对象,用于存储本地变量的值。这个WeakReference对象本身并不保存实际的值,而是保存了一个指向本地变量值的引用。

    • 当访问本地变量时,如果本地变量已经存在,则直接使用已有的变量值;否则,创建一个新的本地变量并保存到ThreadLocalMap中。


    下面是一个使用ThreadLocal的简单案例:

    假设有一个计数器类CountingThreadLocal,它使用ThreadLocal保存计数器的值。在主线程中创建多个子线程,每个子线程都从主线程读取数据,修改计数器的值,设置到自己的本地内存里面,并打印结果。

    一张示意图如下:

     

    代码实现如下:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    public class CountingThreadLocal {
        private static final ThreadLocal counter = new ThreadLocal(){
            @Override
            protected Integer initialValue() {
                return 0;
            }
        };
     
    public static void main(String[] args) {
        for (int i = 0; i < 10; i++) {
                new Thread(() -> {
                    int count = counter.get(); // 获取当前线程的计数器值
                    count++; // 修改计数器值
                    System.out.println("Thread " + Thread.currentThread().getName() + " counts: " + count);
                    counter.set(count); // 将修改后的计数器值保存回ThreadLocal中
                }).start();
            }
        }
    }

    输出结果如下:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    Thread Thread-0 counts: 1
    Thread Thread-4 counts: 1
    Thread Thread-3 counts: 1
    Thread Thread-2 counts: 1
    Thread Thread-1 counts: 1
    Thread Thread-7 counts: 1
    Thread Thread-6 counts: 1
    Thread Thread-5 counts: 1
    Thread Thread-9 counts: 1
    Thread Thread-8 counts: 1

     

    在上述代码中,我们使用ThreadLocal保存了一个Integer类型的计数器值。在主线程中创建多个子线程时,每个子线程都会获取当前线程的计数器值并进行修改。由于使用了ThreadLocal机制,每个线程都有自己的计数器副本,因此不会受到其他线程的影响。最终输出的结果将展示每个线程的计数器值。


    最后我们总结一下:

    • ThreadLocal的实现涉及到三个类:ThreadLocal、ThreadLocalMap和WeakReference。
    • ThreadLocal是一种非常有用的线程局部变量存储机制,它允许每个线程拥有自己的数据副本,从而避免了数据竞争和线程之间的干扰。 

     

  • 相关阅读:
    c 语言基础题目:L1-031 到底是不是太胖了
    PHP反序列化漏洞
    leetcode每日刷题
    CAD DWG 比较--DWG Compare ActiveX Control
    【Rust日报】2023-09-25 Rust + Wasm 是 AGI 的语言吗
    【web-4】Nginx
    【LeetCode-简单题KMP】459. 重复的子字符串
    XiaodiSec day035 Learn Note 小迪安全学习笔记
    【高并发】深度解析线程池中那些重要的顶层接口和抽象类
    10.正则表达式匹配
  • 原文地址:https://www.cnblogs.com/marsitman/p/18148562