【多线程】ThreadLocal 详解,举例说明

ThreadLocal 是 Java 中的一个线程级别的变量,用于在多线程环境下保持变量的独立性。每个线程都可以独立地设置和获取 ThreadLocal 的值,而不会影响其他线程。通常情况下,ThreadLocal 被用来在方法或类之间传递变量。

1、原理:

ThreadLocal 的实现原理是通过维护一个 Map,其中键为线程 ID,值为变量的值。每个线程都有一个唯一的 ID,通过这个 ID 将变量与线程关联起来。当调用 ThreadLocalget 方法时,会根据当前线程的 ID 获取对应的值。当调用 set 方法时,会根据当前线程的 ID 设置对应的值。

2、为什么使用 ThreadLocal:

  • 线程隔离ThreadLocal 提供了一种线程隔离的机制,使得每个线程都可以拥有自己的变量,互不干扰。
  • 避免参数传递: 在多线程环境下,为了传递变量,常常需要在方法之间传递参数。使用 ThreadLocal 可以避免参数传递的繁琐工作,提高代码的简洁性。
  • 线程上下文共享: 在某些情况下,需要在多个方法之间共享某个值,但又不希望使用全局变量。ThreadLocal 提供了一种线程级别的共享机制。

3、使用方法:

public class Example {private static ThreadLocal<String> threadLocal = new ThreadLocal<>();public static void main(String[] args) {// 在线程中设置值threadLocal.set("Hello, ThreadLocal!");// 在不同的方法中获取值method1();method2();}public static void method1() {// 从当前线程获取值String value = threadLocal.get();System.out.println("Method 1: " + value);}public static void method2() {// 从当前线程获取值String value = threadLocal.get();System.out.println("Method 2: " + value);}
}

需要注意的是,在使用完 ThreadLocal 后,尤其是在线程池等场景,应该及时调用 remove 方法,以避免内存泄漏。可以使用 ThreadLocal.remove() 或者使用 try-with-resources 语句块。

public class Example {private static ThreadLocal<String> threadLocal = new ThreadLocal<>();public static void main(String[] args) {try {threadLocal.set("Hello, ThreadLocal!");// 在不同的方法中获取值method1();method2();} finally {// 及时清理 ThreadLocal,避免内存泄漏threadLocal.remove();}}// ...
}

在 Java 8 之后, ThreadLocal 还引入了 withInitial 方法,可以在创建 ThreadLocal 实例的同时初始化其值,进一步简化了使用。

3、实例

import java.util.concurrent.atomic.AtomicInteger;public class ThreadLocalExample {private static final ThreadLocal<Integer> threadLocal1 = new ThreadLocal<>();private static final ThreadLocal<String> threadLocal2 = new ThreadLocal<>();private static final AtomicInteger counter = new AtomicInteger(0);public static void main(String[] args) {Thread thread1 = new Thread(() -> {int value = counter.incrementAndGet();threadLocal1.set(value);threadLocal2.set("Thread " + value);printValues("Thread 1");});Thread thread2 = new Thread(() -> {int value = counter.incrementAndGet();threadLocal1.set(value);threadLocal2.set("Thread " + value);printValues("Thread 2");});thread1.start();thread2.start();}private static void printValues(String threadName) {System.out.println(threadName + " - threadLocal1: " + threadLocal1.get());System.out.println(threadName + " - threadLocal2: " + threadLocal2.get());System.out.println("---");}
}

在这个例子中,两个线程分别递增 counter 并将其值设置到两个不同的 ThreadLocal 变量中。通过 printValues 方法打印每个线程的 ThreadLocal 变量值。由于每个线程有自己的 ThreadLocal 副本,它们之间不会互相干扰。
输出:
在这里插入图片描述

解释: 在这个代码中,有两个线程:thread1 和 thread2。它们共享一个 counter 变量,并使用 threadLocal1 和 threadLocal2 来存储线程本地的值。
.
thread1 启动,counter 的值为0,counter.incrementAndGet() 将 counter 的值增加为1,然后将1设置到 threadLocal1 和 threadLocal2 中。输出线程1的本地值。
.
thread2 启动,counter 的值为1,counter.incrementAndGet() 将 counter 的值增加为2,然后将2设置到 threadLocal1 和 threadLocal2 中。输出线程2的本地值。
.
因为 ThreadLocal 提供了线程本地的变量副本,所以每个线程都可以独立维护自己的值,互不干扰。这就是为什么输出结果中会有 Thread 1 - threadLocal1: 1 和 Thread 2 - threadLocal1: 2 的原因。
.
输出的顺序可能会有差异,因为线程调度的执行顺序不确定。但是每个线程内部的输出是一致的。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/427607.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

java数据结构与算法刷题-----LeetCode667. 优美的排列 II

java数据结构与算法刷题目录&#xff08;剑指Offer、LeetCode、ACM&#xff09;-----主目录-----持续更新(进不去说明我没写完)&#xff1a;https://blog.csdn.net/grd_java/article/details/123063846 解题思路 题目要求我们返回一个数组长度为n的数组&#xff0c;必须含有1~n…

C语言通过IXMLHTTPRequest以get或post方式发送http请求获取服务器文本或xml数据

做过网页设计的人应该都知道ajax。 Ajax即Asynchronous Javascript And XML&#xff08;异步的JavaScript和XML&#xff09;。使用Ajax的最大优点&#xff0c;就是能在不更新整个页面的前提下维护数据。这使得Web应用程序更为迅捷地回应用户动作&#xff0c;并避免了在网络上发…

JS进阶-深入对象(二)

拓展&#xff1a;深入对象主要介绍的是Js的构造函数&#xff0c;实例成员&#xff0c;静态成员&#xff0c;其中构造函数和Java种的构造函数用法相似&#xff0c;思想是一样的&#xff0c;但静态成员和实例成员和java种的有比较大的差别&#xff0c;需要认真理解 • 创建对象三…

el-select选择之后值不显示在文本框的问题解决

问题场景如下图&#xff1a; 在el-collapse-item中使用子组件&#xff0c;子组件里是el-form-item代码。el-select在for循环中&#xff0c;可以有多个。 查了一下博客&#xff0c;有的说这种场景需要给el-select添加change事件&#xff0c;加上 this.$forceUpdate() 强制刷新即…

【单例模式】保证线程安全实现单例模式

&#x1f4c4;前言&#xff1a;本文是对经典设计模式之一——单例模式的介绍并讨论单例模式的具体实现方法。 文章目录 一. 什么是单例模式二. 实现单例模式1. 饿汉式2. 懒汉式2.1 懒汉式实现单例模式的优化&#xff08;一&#xff09;2.2 懒汉式实现单例模式的优化&#xff08…

仿真机器人-深度学习CV和激光雷达感知(项目2)day04【简单例程】

文章目录 前言简单例程运行小海龟仿真启动节点查看计算图发布 Topic调用 Serviece 用 Python 发布和接收 Topic创建工作空间创建功能包&#xff0c;编译编写 Topic Publisher 节点编写 Topic Subscriber 节点运行节点 自定义消息类型用 Python 注册和调用 Serviece新建功能包在…

【若依】关于对象查询list返回,进行业务处理以后的分页问题

1、查询对象Jglkq返回 list&#xff0c;对 list 进行业务处理后返回&#xff0c;但分页出现问题。 /*** 嫁功率考勤查询*/RequiresPermissions("hr:kq:list")PostMapping("/list")ResponseBodypublic TableDataInfo list(Jglkq jglkq) throws ParseExcepti…

Spring基于dynamic-datasource实现MySQL多数据源

目录 多数据源实现 引入依赖 yml配置文件 业务代码 案例演示 多数据源实现 引入依赖 <dependency><groupId>com.baomidou</groupId><artifactId>dynamicdatasourcespringbootstarter</artifactId><version>3.5.0</version> &…

[Python] glob内置模块介绍和使用场景(案例)

Unix glob是一种用于匹配文件路径的模式&#xff0c;它可以帮助我们快速地找到符合特定规则的文件。在本文中&#xff0c;我们将介绍glob的基本概念、使用方法以及一些实际应用案例。 glob介绍 Glob(Global Match)是Unix和类Unix系统中的一种文件名扩展功能&#xff0c;它可以…

【python文件】生成的csv文件没两行数据之间有一个空行

问题描述 用python代码将数据写入csv文件&#xff0c;但生成的csv文件没两行数据之间有一个空行&#xff0c;如下图所示&#xff1a; 解决办法 在open函数中添加newline&#xff0c;如以下代码所示&#xff0c;即可解决这一问题。 with open(r"C:\Users\xxx\Desktop\DR…

未来已来:AI引领智能时代的多领域巨变

大家好&#xff0c;今天我们将深入探讨人工智能如何彻底改变我们的生活方式&#xff0c;领略未来的无限可能性。 1. 医疗革新&#xff1a;AI担任超级医生 医疗领域是AI最引人注目的战场之一。智能医学影像诊断系统&#xff0c;不仅能够精准识别病变&#xff0c;还能辅助医生提…

使用人工智能助手 Github Copilot 进行编程 02

本章涵盖了 在您的系统上设置 Python、VS Code 和 Copilot引⼊ Copilot 设计流程Copilot 的价值在于基本的数据处理任务本章将帮助您在自己的计算机上开始使用 Copilot,并熟悉与其的交互方式。在设置好Copilot 后,我们将要求您尽可能跟随我们的示例进行操作。实践是最好的学习…