首页 > 编程语言 >Java面试题:请谈谈对ThreadLocal的理解?

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

时间:2024-04-21 09:15:04浏览次数:28  
标签:面试题 Java Thread 计数器 ThreadLocal 线程 counts WeakReference

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

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

下图可以增强理解:

 

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

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

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

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


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

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

一张示意图如下:

 

代码实现如下:

public class CountingThreadLocal {
    private static final ThreadLocal<Integer> counter = new ThreadLocal<Integer>(){
        @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();
        }
    }
}

输出结果如下:

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是一种非常有用的线程局部变量存储机制,它允许每个线程拥有自己的数据副本,从而避免了数据竞争和线程之间的干扰。 

 

标签:面试题,Java,Thread,计数器,ThreadLocal,线程,counts,WeakReference
From: https://www.cnblogs.com/marsitman/p/18148562

相关文章

  • [转帖]十年拉锯战终结束,Google 赢得 Java API 版权诉讼
    https://www.oschina.net/news/136073/googles-wins-lawsuit Google和Oracle(甲骨文)在法庭上就Android操作系统中Java编程语言的使用问题争吵了十年。美国最高法院在周一以6比2的投票结果裁定,Google对Java代码的使用被归为"合理使用",没有违反联邦版权法......
  • [转帖]Oracle 败了、谷歌赢了:Java API 版权案最终裁决
    https://zhuanlan.zhihu.com/p/362496136 周一,最高法院在Oracle围绕移动操作系统Android中所用软件的一起旷日持久的版权诉讼中判谷歌胜诉。法院的判决为6比2。大法官AmyConeyBarrett没有参与此案。该案涉及谷歌用于构建Android的12000行代码,这些代码是从SunMicrosy......
  • Solon Java 应用开发框架 v2.7.5 发布
    JavaSolon是什么框架?Java“新的”应用开发框架。从零开始构建(非java-ee架构),有灵活的接口规范与开放生态。追求:更快、更小、更简单提倡:克制、简洁、高效、开放、生态有什么特点?更高的计算性价比:并发高2~3倍;内存省50%更快的开发效率:内核小,入门快;调试重启快5......
  • 最新Java面试题带答案【2024中级】
    互联网大厂面试题1:阿里巴巴Java面试题2:阿里云Java面试题-实习生岗3:腾讯Java面试题-高级4:字节跳动Java面试题5:字节跳动Java面试题-大数据方向6:百度Java面试题7:蚂蚁金服Java面试题-中级8:蚂蚁金服Java面试题-高级9:京东Java面试题-中级10:拼多多Java面试题-电商部11:商汤科技......
  • java 异步任务,定时任务,邮件发送
    java异步任务,定时任务,邮件异步任务异步方法注解:@Async主程序开启异步注解功能:@EnableAsync定时任务开启定时功能的注解在main:@EnableSchedulingTaskScheduler:任务调用者TaskExecutor:任务执行者@EnableScheduling开启定时功能的注解@Scheduled固定......
  • Java 安全基础之 Java 反射机制和 ClassLoader 类加载机制
    目录Java反射机制反射java.lang.RuntimeClassLoader类加载机制URLClassLoaderJava反射机制Java反射(Reflection)是Java非常重要的动态特性。在运行状态中,通过Java的反射机制,我们能够判断一个对象所属的类。了解任意一个类的所有属性和方法。能够调用任意一个对象的任意方......
  • java Swagger 使用汇总
    Swagger1.Swagger简介最流行的api框架restfulapi在线自动生成工具:api文档与api定义同步更新直接运行,可以在线测试api接口支持多种语言:java,php2.官网https://swagger.io在项目中使用swagger需要springboxswagger2ui3.SpringBoot集成Swaggerhttps://mvnreposito......
  • Java面试题:为什么HashMap不建议使用对象作为Key?
    HashMap是一种基于哈希表的动态数据结构,它允许使用任意不可变对象作为键(key)来存储和检索数据。然而,在某些情况下,使用对象作为HashMap的键可能会遇到一些问题。 首先,我们需要明确对象作为HashMap的键需要满足一些条件:不可变性:对象的属性不能被修改,因为如果属性被修改,那......
  • JavaScript变量的奥秘:从声明到使用,一文掌握!
    在编程的世界里,数据是构建一切的基础。而在JavaScript中,变量就是存储数据的容器。它们就像是我们生活中的盒子,可以装下各种物品,让我们在需要的时候随时取用。今天,就让我们一起揭开变量的神秘面纱,探索它们的概念、使用规则,以及那些令人头疼的错误。一、变量的概念和作用变量,顾名......
  • 01、Java 安全-反序列化基础
    Java反序列化基础1.ObjectOutputStream与ObjectInputStream类1.1.ObjectOutputStream类java.io.ObjectOutputStream类,将Java对象的原始数据类型写出到文件,实现对象的持久存储。序列化操作一个对象要想序列化,必须满足两个条件:该类必须实现java.io.Serializable接口,......