JUC并发工具---ThreadLocal

ThreadLocal适合用在哪些实际生产的场景中

适用场景

场景一场景二
ThreadLocal用作保存每个线程独享的对象ThreadLocal用作每个线程内需要独立保存信息以便其他方法更方便地获取该信息的场景(类似于全局变量的概念)
通常用于保存线程不安全的工具类,典型的需要使用的类就是SimpleDateFormat。每个线程内需要保存类似于全局变量的信息 (例如在拦截器中获取的用户信息)可以让不同方法直接使用避免参数传递的麻烦却不想被多线程共享 (因为不同线程获取到的用户信息不一样)
每个Thread内都有自己的实例副本,且该副本只能由当前Thread访问到并使用,相当于每个线程内部的本地变量用ThreadLocal保存一些业务内容(用户权限信息、从用户系统获取到的用户名、用户ID等)
这些信息在同一个线程内相同,但是不同的线程使用的业务内容是不相同的
在线程生命周期内,都通过这个静态ThreadLocal实例的get()方法取得自己set过的那个对象
避免了将这个对象(如user对象)作为参数传递的麻烦
import java.sql.Date;
import java.text.SimpleDateFormat;public class ThreadLocalDemo02 {public static void main(String[] args) throws InterruptedException {int numberOfThreads = 1000;for (int i = 0; i < numberOfThreads; i++) {int finalI = i;new Thread(() -> {String date = new ThreadLocalDemo02().date(finalI);System.out.println(date);}).start();}// 确保主线程等待所有子线程完成Thread.sleep(1000); // 增加等待时间以确保所有线程都能完成}public String date(int seconds) {// 获取当前时间Date date = new Date(1000 * seconds);// 格式化时间SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");return simpleDateFormat.format(date);}
}
import java.sql.Date;
import java.text.SimpleDateFormat;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;public class ThreadLocalDemo02 {public static ExecutorService threadPool = Executors.newFixedThreadPool(16);static SimpleDateFormat dateFormatHolder = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");public static void main(String[] args) throws InterruptedException {for (int i = 0; i < 1000; i++) {int finalI = i;threadPool.submit(new Runnable(){@Overridepublic void run() {String date = new ThreadLocalDemo02().date(finalI);System.out.println(date);}});}threadPool.shutdown();}public String date(int seconds){//获取当前时间Date date = new Date(1000*seconds);//格式化时间String s = null;// 使用synchronized会导致排队,其实也没有合理用到线程池synchronized(ThreadLocalDemo02.class) {s = dateFormatHolder.format(date);}return s;}
}
import java.sql.Date;
import java.text.SimpleDateFormat;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;public class ThreadLocalDemo02 {public static ExecutorService threadPool = Executors.newFixedThreadPool(16);// 这个时候只创建了16个SimpleDateFormat对象public static void main(String[] args) throws InterruptedException {for (int i = 0; i < 1000; i++) {int finalI = i;// 16个线程对应16个simpleDateFormat对象,每个线程有自己的副本,是线程安全的threadPool.submit(new Runnable(){@Overridepublic void run() {String date = new ThreadLocalDemo02().date(finalI);System.out.println(date);}});}threadPool.shutdown();}public String date(int seconds){//获取当前时间Date date = new Date(1000*seconds);//格式化时间return ThreadSafeFormatter.formatterHolder.get().format(date);}}class ThreadSafeFormatter {public static ThreadLocal<SimpleDateFormat> formatterHolder = new ThreadLocal<SimpleDateFormat>(){protected SimpleDateFormat initialValue(){return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");}};
}
public class ThreadLocalDemo03 {public static void main(String[] args) {new Service1().service1();}
}class Service1 {public void service1() {User user = new User("user1");UserContextHolder.holder.set(user);new Service2().service2();}
}class Service2 {public void service2() {User user = UserContextHolder.holder.get();System.out.println("Service2 user name: " + user.getName());new Service3().service3();}
}class Service3 {public void service3() {User user = UserContextHolder.holder.get();System.out.println("Service3 user name: " + user.getName());// 避免无限递归调用}
}class UserContextHolder {public static ThreadLocal<User> holder = new ThreadLocal<>();
}class User {private String name;public User(String name) {this.name = name;}public String getName() {return name;}public void setName(String name) {this.name = name;}
}

ThreadLocal是不是用来解决共享资源的多线程访问的呢

答案:不是,ThreadLocal虽然可以用于解决多线程情况下的线程安全问题,但其资源不是共享的,而是每个线程独享的。可以在initialValue中new出自己线程独享的资源,而多个线程之间,它们所访问的对象本身是不共享的,自然就不存在任何并发问题。

如果需要放到ThreadLocal中的这个对象是共享的,是被 static 修饰的即使用了ThreadLocal并不能解决线程安全问题。

对于共享的变量,如果想要保证它的线程安全,应该用其他的方法比如说可以使用synchronized或者是加锁等其他的方法来解决线程安全问题而不是使用ThreadLocal,因为这不是ThreadLocal应该使用的场景

ThreadLocal和synchronized是什么关系?

当ThreadLocal用于解决线程安全问题时,也就是把一个对象给每个线程都生成一份独享的副本的,这种场景下,ThreadLocal和synchronized都可以理解为是用来保证线程安全的手段。但是效果和实现原理不同:

  • ThreadLocal是通过让每个线程独享自己的副本,避免了资源的竞争
  • synchronized 主要用于临界资源的分配,在同一时刻限制最多只有一个线程能访问该资源

相比于ThreadLocal而言,synchronized 的效率会更低一些,但是花费的内存也更少,在这种场景下,ThreadLocal和 synchronized 都可以达到线程安全的目的

对于ThreadLocal而言,它还有不同的使用场景,比如当ThreadLocal用于让多个类能更方便地拿到我们希望给每个线程独立保存这个信息的场景下时(比如每个线程都会对应一个用户信息,也就是user对象),在这种场景下,ThreadLocal侧重的是避免传参,此时ThreadLocal和 synchronized 是两个不同维度的工具。

多个ThreadLocal在Thread中的threadlocals是怎么存储的

三者的关系

[外链图片转存中…(img-uWLWNTd1-1734882917433)]

get()方法

[外链图片转存中…(img-ggtLn05S-1734882917433)]

[外链图片转存中…(img-JVxdHiAg-1734882917433)]

[外链图片转存中…(img-GyR5f8Jt-1734882917433)]

内存泄漏:每次用完ThreadLocal都要调用remove()

内存泄漏

当某个对象不再有用的时候,占用的内存却不能被回收。

[外链图片转存中…(img-HTkqftbA-1734882917433)]

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

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

相关文章

解决uniapp中使用axios在真机和模拟器下请求报错问题

由于我的uniapp项目是通过vite脚手架搭建的&#xff0c;当时选择了axios作为请求方式&#xff0c;在本地调试的时候也一直没发现有问题&#xff0c;直到打包成app在真机上登录&#xff0c;发现报错There is no suitable adapter to dispatch the request since:-adapter xhr is…

python coding(二) Pandas 、PIL、cv2

Pandas 一个分析结构化数据的工具集。Pandas 以 NumPy 为基础&#xff08;实现数据存储和运算&#xff09;&#xff0c;提供了专门用于数据分析的类型、方法和函数&#xff0c;对数据分析和数据挖掘提供了很好的支持&#xff1b;同时 pandas 还可以跟数据可视化工具 matplotli…

第十五届蓝桥杯Scratch01月stema选拔赛—排序

排序 具体要求&#xff1a; 1). 点击绿旗&#xff0c;在舞台上出现4张点数不同的扑克牌&#xff0c;牌上的点数是随机的&#xff08;4-9点&#xff09;&#xff0c;如图所示&#xff1b; 完整题目可点击下方链接查看&#xff1a; 排序_scratch_嗨信奥-玩嗨信息奥林匹克竞赛-…

图形 3.4 延迟渲染管线介绍

延迟渲染管线介绍 B站视频&#xff1a;图形 3.4 延迟渲染管线介绍 文章目录 延迟渲染管线介绍渲染路径前向渲染渲染流程光照规则 延迟渲染渲染流程几何缓冲区 G-buffer 不同渲染路径的优劣以及特性优劣 Unity中渲染路径设置移动端优化分块延迟渲染 其他渲染路径不同路径下光源…

Qt之串口设计-线程实现(十二)

Qt开发 系列文章 - Serial-port&#xff08;十二&#xff09; 目录 前言 一、SerialPort 二、实现方式 1.创建类 2.相关功能函数 3.用户使用 4.效果演示 5.拓展应用-实时刷新 总结 前言 Qt作为一个跨平台的应用程序开发框架&#xff0c;在串口编程方面提供了方便易用…

智能体实战(需求分析助手)一、需求概述及迭代规划

需求分析助手开发迭代规划 功能概述 需求分析助手是一款基于大模型的智能系统,旨在帮助用户高效完成需求获取、需求分析、需求文档编写及需求验证的全流程工作。通过对用户输入的智能处理和分析,需求分析助手能够简化需求管理流程,并根据不同业务场景提供定制化支持。 核心…

1.gitlab 服务器搭建流程

前提条件&#xff1a; 一、服务器硬件水平 搭建gitlab服务器最低配置要求2核4G,低于这个配置的服务器运行效果很差。 gitlab官网&#xff1a;https://about.gitlab.com/ 下载地址&#xff1a;gitlab/gitlab-ce - Packages packages.gitlab.com 本机ubuntu 二、安装依赖 su…

Eclipse 添加书签

Eclipse 添加书签 Eclipse 是一款非常受欢迎的集成开发环境&#xff08;IDE&#xff09;&#xff0c;广泛用于 Java、C、Python 等语言的开发。在处理大型项目时&#xff0c;开发者通常需要在不同文件和代码行之间频繁切换。为了提高工作效率&#xff0c;Eclipse 提供了书签功…

powerhsell 初认识

免责声明 本文是学习与泷羽Sec B站课程的课程笔记内容&#xff0c;仅作学习使用&#xff0c;如有破坏网络安全的行为&#xff0c;本人概不负责 B站链接&#xff1a;https://space.bilibili.com/350329294 资源自取&#xff1a;https://pan.quark.cn/s/b2718e905db8 powerhsel…

自我维护和保养

学习运动两不误&#xff01; 本人学习过程中&#xff0c;长期久坐导致各种身体问题&#xff08;特别是腰间盘突出&#xff0c;右侧肩胛骨翘等问题&#xff01;&#xff09;&#xff0c;希望给有类似烦恼的人们带去福音&#xff01;&#xff01;&#xff01; 我的椎间盘损伤历…

详解磁盘IO、网络IO、零拷贝IO、BIO、NIO、AIO、IO多路复用(select、poll、epoll)

1、什么是I/O 在计算机操作系统中&#xff0c;所谓的I/O就是输入&#xff08;Input&#xff09;和输出&#xff08;Output&#xff09;&#xff0c;也可以理解为读&#xff08;Read&#xff09;和写&#xff08;Write)&#xff0c;针对不同的对象&#xff0c;I/O模式可以划分为…

windows的服务怎么删除

在 Windows 上&#xff0c;如果你想删除一个服务&#xff08;例如 Redis 服务&#xff09;&#xff0c;你可以使用命令行工具来删除它。以下是删除服务的几种方法&#xff1a; 1. 使用 sc delete 命令删除服务 sc 是 Windows 提供的一个命令行工具&#xff0c;用于与服务控制…

Cursor的重磅功能Agent登场

今天看了一些介绍&#xff0c;cursor有一个新功能agent ,试用了一下非常好用。再也不用头痛地选择相关的上下文&#xff0c;真是懒人利器。 Agant特性&#xff1a; 可以自主选择上下文能够使用终端可以独立完成整个任务 赶紧介绍给大家&#xff0c;使用时&#xff0c;需要在c…

5G -- 空口关键技术

前言&#xff1a; 手机(UE)和5G基站(gNodeB)之间的空中接口 新技术的特点&#xff1a; 1、提升速率&#xff1a;大带宽、新编码、高阶调制、F-OFDM、M-MIMO 2、降低时延&#xff1a;灵活帧结构、自包含时隙、免授权调度、D2D 3、提升覆盖&#xff1a;上下行解耦、EN-DC(双连…

常用Python自动化测试框架有哪些?

随着技术的进步和自动化技术的出现&#xff0c;市面上出现了一些自动化测试框架。只需要进行一些适用性和效率参数的调整&#xff0c;这些自动化测试框架就能够开箱即用&#xff0c;大大节省了测试时间。而且由于这些框架被广泛使用&#xff0c;他们具有很好的健壮性&#xff0…

堆排序【东北大学oj数据结构9-4】C++

堆排序是一种基于堆的数据结构的排序&#xff0c;是一种快速排序算法&#xff0c;可以在输入数组中实现排序处理&#xff08;内存高效&#xff09;。 堆排序可以实现如下&#xff1a; maxHeapify(A, i) l left(i) r right(i) // select the node which has the m…

【自用】通信内网部署rzgxxt项目_01,后端pipeDemo部署(使用nssm.exe仿照nohup)

做完这些工作之后&#xff0c;不要忘记打开 Windows Server 的防火墙端口&#xff0c;8181、8081、8080、22、443、1521 做完这些工作之后&#xff0c;不要忘记打开 Windows Server 的防火墙端口&#xff0c;8181、8081、8080、22、443、1521 做完这些工作之后&#xff0c;不要…

jmeter 接口性能测试 学习笔记

目录 说明工具准备工具配置jmeter 界面汉化配置汉化步骤汉化结果图 案例1&#xff1a;测试接口接口准备线程组添加线程组配置线程组值线程数&#xff08;Number of Threads&#xff09;Ramp-Up 时间&#xff08;Ramp-Up Period&#xff09;循环次数&#xff08;Loop Count&…

Clickhouse(Centos)

地址信息 官网地址&#xff1a;Fast Open-Source OLAP DBMS - ClickHouse 下载地址&#xff1a;packages.clickhouse.com/rpm/stable/ 1.clickhouse-client-23.1.3.5.x86_64.rpm 2.clickhouse-common-static-23.1.3.5.x86_64.rpm 3.clickhouse-common-static-dbg-23.1.3.5.x86_…

iOS开发 UIAlertView与UIActionSheet替换方案之SDAlertView与SDActionSheet

iOS开发 UIAlertView与UIActionSheet替换方案之SDAlertView与SDActionSheet 由于在iOS开发中&#xff0c;项目中还在使用UIAlertView与UIActionSheet&#xff0c;由于这两个类在iOS开始废弃 UIKIT_EXTERN API_DEPRECATED(“UIAlertView is deprecated. Use UIAlertController…