ThreadLocal实现线程范围的共享变量-笔记整理4

【珍藏版】80道Java多线程并发经典面试题 前言 个人珍藏的80道Java多线程/并发经典面试题,因为篇幅太长,现在先给出1-10的答案解析哈,后面一起完善,并且上传github哈~ github.com/whx123/Java… ❞ 1. synchronized的实现原理以及锁优化? synchronized的实现原理 synchronized作用于「方法」或者「代码块」,保证被修饰的代码在同一时间只能被一个线程访问。 synchronized修饰代码块时,JVM采用「monitorenter、monitorexit」两个指令 阅读详情

线程范围内共享变量的概念与作用

 

1.作用和目的:用于实现线程内的数据共享,即对于相同的程序代码,多个模块在同一个线程中运行时要共享一份数据,而在另外线程中运行时又共享另外一份数据。

2.每个线程调用全局ThreadLocal对象的set方法,就相当于往其内部的map中增加一条记录,key分别是各自的线程,value是各自的set方法传进去的值。在线程结束时可以调用ThreadLocal.clear()方法,这样会更快释放内存,不调用也可以,因为线程结束后也可以自动释放相关的ThreadLocal变量。

3.ThreadLocal的应用场景:

       (1)订单处理包含一系列操作:减少库存量,增加一条流水台账,修改总账,这几个操作要在同一个事务中完成,通常也即同一个线程中进行处理,如果累加公司应收款的操作失败了,则应该把前面的操作回滚,否则,提交所有的操作,这要求这些操作使用相同的数据库连接对象,而这些操作的代码分别位于不同的模块类中。

       (2)例如Strut2的ActionContext,同一段代码被不同的线程调用运行时,该代码操作的数据是每个线程各自的状态和数据,对于不同的线程来说,getContext方法拿到的对象都不相同,对同一个线程来说,不管调用getContext方法多少次和在哪个模块中getContext方法,拿到的都是同一个。

(3)实例案例:定义一个全局共享的ThreadLocal变量,然后启动多个线程向该ThreadLocal变量中存储一个随机值,接着看各个线程调用另外其他多个类的方法,这多个类的方法中读取这个ThreadLocal变量的值,就可以看到多个类在同一个线程中共享同一份数据。


重点:(4)实现对ThreadLocal变量的封装,让外界不要直接操作ThreaLocal变量。

对基本类型的数据的封装,这种应用相对很少见。

对对象类型的数据的封装,比较常见,即让某个类针对不同线程分别创建一个独立的实例对象。



实例1:自定义一个map实现ThreadLocal实现线程间数据独立,在使用ThreadLocal来实现,加深对ThreadLocal原理大的理解

public class ThreadScopeShareData {
//	private static int data=0;
/*	private static Map<Thread,Integer>  map  = new HashMap<Thread,Integer>();*/
	private static ThreadLocal<Integer> map  = new ThreadLocal<Integer>();
	public static void main(String[] args){
		for(int i=0;i<2;i++){
		 new Thread(new Runnable(){
			
			public void run() {
				 int data  = new Random().nextInt();
				 System.out.println(Thread.currentThread().getName()+"has put data"+data);
				/* map.put(Thread.currentThread(), data);*/
				 map.set(data);
				 new A().get();
				 new B().get();
			}
		 }).start();
		 
		}
	}
static class A{
/*	 public void get(){
		 System.out.println("A  from"+Thread.currentThread().getName()+"get  data"+map.get(Thread.currentThread()));
	 }*/
	public void get(){
		System.out.println("A  from  "+Thread.currentThread().getName()+" get  data  "+map.get());
	}
}
static class B{
/*	 public void get(){
		 System.out.println("B  from"+Thread.currentThread().getName()+"get  data"+map.get(Thread.currentThread()));
	 }*/
	public void get(){
		System.out.println("B  from  "+Thread.currentThread().getName()+" get  data  "+map.get());
	}
}
}


实例2:当数据较多时,将多个数据惊醒封装,使用引用类型数据

public class ThreadLocalText {
		/* private static ThreadLocal<Integer> map  = new ThreadLocal<Integer>();*/
			public static void main(String[] args){
				for(int i=0;i<2;i++){
				 new Thread(new Runnable(){
					
					public void run() {
						 int data  = new Random().nextInt();
						 System.out.println(Thread.currentThread().getName()+"  has put data  "+data);
						/* map.put(Thread.currentThread(), data);*/
						 /*map.set(data);*/
						 MyThreadLocal.getInstance().setName("name"+data);
						 MyThreadLocal.getInstance().setAge(data);
						 new A().get();
						 new B().get();
					}
				 }).start();
				 
				}
			}
			
		static class A{
		/*	 public void get(){
				 System.out.println("A  from"+Thread.currentThread().getName()+"get  data"+map.get(Thread.currentThread()));
			 }*/
			public void get(){
				/*System.out.println("A  from  "+Thread.currentThread().getName()+" get  data  "+map.get());*/
				MyThreadLocal mydata = MyThreadLocal.getInstance();
				System.out.println("A  from "+Thread.currentThread().getName()+mydata.getName()+"  get  data  "+mydata.getAge());
			}
		}
		static class B{
		/*	 public void get(){
				 System.out.println("B  from"+Thread.currentThread().getName()+"get  data"+map.get(Thread.currentThread()));
			 }*/
			public void get(){
				/*System.out.println("B  from  "+Thread.currentThread().getName()+" get  data  "+map.get());*/
				MyThreadLocal mydata = MyThreadLocal.getInstance();
				System.out.println("B  from "+Thread.currentThread().getName()+mydata.getName()+"  get  data  "+mydata.getAge());
			}
		}
	 static class MyThreadLocal{
		  private String name;
		  private int age;
		  
		  private MyThreadLocal(){}
		  
		  public static MyThreadLocal getInstance(){
			  MyThreadLocal instance =map.get();
			   if(instance==null){
				   instance = new MyThreadLocal();
				   map.set(instance);
			   }
			   return instance;
		  }
		
		  private  static ThreadLocal<MyThreadLocal>  map  = new ThreadLocal<MyThreadLocal>();
		
		/*private MyThreadLocal instance = null;*/
		public String getName() {
			return name;
		}
		public void setName(String name) {
			this.name = name;
		}
		public int getAge() {
			return age;
		}
		public void setAge(int age) {
			this.age = age;
		}
	 }
}



LabVIEW小白福音:手把手教你用NI采集卡搭建振动信号采集系统(附源码和避坑指南) 本文为LabVIEW初学者提供详细的NI采集卡振动信号采集系统搭建指南,涵盖硬件连接、驱动安装、信号处理及性能优化等关键步骤。特别针对振动信号采集系统中的常见问题提供解决方案,并附源码和避坑指南,帮助用户快速上手并避免常见错误。 阅读详情

相关推荐

Android逆向分析

Android 逆向开发是指对已发布的 Android 应用进行分析和破解,以了解应用程序的内部工作原理,获取应用程序的敏感信息,或者修改应用程序的行为。Android应用 Java编写的,利用Android SDK编译代码,并并且把所有的数据和资源文件打包成一个APK(Android Package)文件这是一个后缀名为.apk的压缩文件,apk文件中包含了一个Anddroid应用程序的所有内容,是Android平台用于安装应用程序的文件。

qq_51598534的博客 6293

Tomcat中的内存泄漏问题

停止Tomcat服务的时候,log里面报了不少的内存错误信息。经查询是Tomcat6.0.24以后会检测到的问题。 Summary matrix Leak cause Detected by tomcat Fixed by tomcat Possible enhancements Custom ThreadLocal cl

步行者的专栏 5213

Theil-Sen Median斜率估计和Mann-Kendall趋势分析:以多年NPP数据为例

一、理论 Theil-Sen Median方法又称为Sen斜率估计,是一种稳健的非参数统计的趋势计算方法。该方法计算效率高,对于测量误差和利群数据不敏感,适用于长时间序列数据的趋势分析。其计算公式为: Mann-Kendall(MK)检验是一种非参数的时间序列趋势性检验方法,其不需要测量值服从正太分布,不受缺失值和异常值的影响,适用于长时间序列数据的趋势显著检验。其过程如下:对 于 序 列Xt = x1,x2,⋯xn,先确定所有对偶值( xi , xj ,...

丑唐的修炼之旅 8万+

tomcat关闭应用时的清理工作

http://hongjiang.info/tomcat-jdbc-leak-prevention/

博茨瓦纳的狮王 2846

【工具】GitHub学生认证+PyCharm配置Copilot全流程指南

本文提供了一份详细的GitHub学生认证及在PyCharm中配置Copilot的完整指南。通过完成A2F认证、准备有效材料并使用干净网络环境,学生可免费获取GitHub Copilot Pro订阅,极大提升编程学习与开发效率。

w7x8y9z的博客 1457

基于本地知识库的智能问答系统架构

智能问答系统的核心可以分为4部分。1)知识库构建。2)检索。3)后处理。4)推理。知识库构建:知识库中可以包含多个向量数据库和知识图谱等,核心是怎么建立索引,使得检索时能够将与问题相关的知识给检索出来。检索:从知识库中的多个库或者知识图谱中检索出与问题相关的信息。后处理:从知识库中检索出来的信息可能是冗余的,而且可能不符合我们希望的格式要求,因此,我们需要对这些数据进行过滤,格式化等操作。推理: 基于检索出来的知识进行推理,让输出能够回答用户的问题,目前主要使用大模型进行推理。

qq_44993593的博客 1709

java thread 清除_java – 如何清理threadlocals

javadoc说:“Each thread holds an implicit reference to its copy of a thread-local variable as long as the thread is alive and the ThreadLocal instance is accessible; after a thread goes away, all of its...

weixin_34061440的博客 2644

STM32使用LORA模块通信

目录 一、模块使用方法 1、模块简介 2、硬件及功能 3、传输方式 二、模块上手 1、连接 2、编写代码 usart3.h usart3.c lora.h lora.c 一、模块使用方法 本文以正点原子ATK-LORA-01模块为例进行介绍。 1、模块简介 ATK-LORA-01-V3.0(V3.0是版本号,下面均以ATK-LORA-01表示该产品)是ALIENTEK推出的一款体积小、微功率、低功耗、高性能远距离LORA无线串口模块。模块设计是采用高效的IS...

qq_54706971的博客 3万+

Java解读-ThreadLocal详解与应用

ThreadLocal概念 ThreadLocal 字面意思来看有点像“线程的本地实现版本”,实际上真正含义是ThreadLocalVariable(线程本地局部变量),所以把它命名为ThreadLocalVar更加合适。 ThreadLocal 是用来解决共享对象(单个线程内共享)的多线程访问问题的,使用场合主要解决多线程中数据因并发产生不一致问题。 T...

高广超的博客 365

AI 辅助编程全景:演进、提效场景与未来趋势

本文系统梳理了AI辅助编程的发展历程与应用场景。演进路径分为三代:从代码补全工具(2023)、对话式助手(2024)到自主编程代理(2025)。在软件全生命周期中,AI可显著提升各环节效率:需求分析阶段节省30-60%文档编写时间;设计阶段缩短40-60%技术调研周期;编码阶段通过智能补全提升55%任务速度;测试阶段减少30-60%测试编写时间。数据显示,2025年84%开发者使用AI工具,41%代码由AI生成,平均每周节省3.6小时。AI正推动开发者角色从编写者转变为审核者,但复杂业务逻辑和架构设计仍需人

甘蓝的专栏 472

提示词编程在自动化内容审核中的应用

文章标题 提示词编程在自动化内容审核中的应用 关键词:提示词编程,自动化内容审核,人工智能,算法原理,系统架构设计,项目实战 摘要 本文旨在探讨提示词

AI天才研究院 1252

ThreadLocal

维持线程封闭性的一种更规范方法是使用ThreadLocal,这个类能使线程中的某个值与保存值的对象 关联起来。ThreadLocal提供了get与set等访问接口或方法,这些方法为每个使用该变量的线程都存有 一份独立的副本,因此get总是返回由当前执行线程在调用set时设置的最新值。    ThreadLocal对象通常用于防止对可变的单实例变量(singleton)或全局变量进行共享。例如

neutrojan的专栏 762

lwip-2.0.3

lwip是瑞典计算机科学院(SICS)的Adam Dunkels 开发的一个小型开源的TCP/IP协议栈。实现的重点是在保持TCP协议主要功能的基础上减少对RAM 的占用。

多线程(六)线程同步(下)-ThreadLocal,阻塞队列

这篇主要是为了扩展了解线程同步,在多线程(七)中将重点讲述线程队列。本文转载自:(http://www.cnblogs.com/duanxz/p/3709608.html?utm_source=tuicool&utm_medium=referral)<六>使用局部变量实现线程同步  如果使用ThreadLocal管理变量,则每一个使用该变量的线程都获得该变量的副本,副本之间相互独立,这样每一个线程都

淡淡的倔强的博客 2469

SIMATIC S7-1200, S7-1500 PID 控制[手册]

SIMATIC S7-1200, S7-1500 PID 控制[手册]

pscad IEEE标准系统搭建说明

pscad IEEE标准系统搭建说明,包含典型的IEEE 9节点、14节点、30节点、39节点和118节点系统。内含标准测试系统的原始数据和潮流结果。

彻底理解ThreadLocal

ThreadLocal 是 Java 中的一个类,用于实现线程本地变量(本地线程变量),即每个线程都可以拥有自己独立的变量副本。ThreadLocal 提供了一种简单的方式,让每个线程都拥有自己的变量,线程之间互不干扰。

共同学习,共同成长! 509

怀旧版电脑GBC模拟器

再现原版GBC掌机的界面,电脑运行连游戏界面都一样大小,很怀旧,很真实,(英文版)强烈推荐,很小的文件,很难才找到的。

线程和锁自整理面试题

1.线程的实现方式 常见的有3种: Thread:继承Thread类,start启动线程,重写run方法执行。 Runnable:实现Runnable接口,start启动线程,重写run方法执行。 Callable:实现Callable接口,start启动线程,并实现其call()方法。能返回指定的参数。 接口的start方法都是通过Thread调用。 2.线程的执行流程。 新建:创建了线程。 就绪:执行start(),进入队列,等待JVM的调度。 运行:得到CPU时间片开始执行run方法,可以变为阻

hung_jun的博客 633

Android 面试主题集合整理,Android进阶学习资料

4)线程执行某些 IO 操作,因为等待相关资源而进入了阻塞态,如 System.in, 但没有收到键盘的输入,则进入阻塞态。 5)线程礼让,Thread.yield()方法,暂停当前正在执行的线程对象,把执行机会 让给相同或更高优先级的线程,但并不会使线程进入阻塞态,线程仍处于可执行 态,随时可能再次分得 CPU 时间。线程自闭,join()方法,在当前线程调用另一个线程的 join()方法,则当前线程进入阻塞态,直到另一个线程运行结束,当前 线程再由阻塞转为就绪态。 6)线程执行 suspend()使线程

m0_66155412的博客 691

网络编程面试题整理(四)

1:重传机制 TCP每发送一个报文段,就设置一次定时器。只要定时器设置的重发时间到而还没有收到确认,就要重发这一报文段。  TCP环境报文往返时间不定、有很大差别。 A、B在一个局域网络,往返时延很小 A、C在一个互联网内,往返时延很大 因此,A很难确定一个固定的、与B、C通信都适用的定时器时间。 ...

帅泽泽的博客 197

知识整理

目录 多线程 多线程的使用场景 在不阻塞主线程的基础上启动其它线程去完成某些比较耗时的任务,例如JavaWeb就是主线程监听用户Http请求,然后启动子线程去处理用户http请求。Jvm垃圾回收。 如何使用多线程 两种方式,继承Thread类,实现Runnable接口。Java是单继承,更多使用实现接口。new 一个Thread后,执行start启动子线程。 Runnabl

sunday的博客 454

Android 面试主题集合整理

2)线程执行一段同步代码,但无法获得相关的同步锁,只能进入阻塞状态,等 到获取到同步锁,才能恢复执行; 3)线程执行了一个对象的 wait()方法,直接进入阻塞态,等待其他线程执行 notify()/notifyAll()操作; 4)线程执行某些 IO 操作,因为等待相关资源而进入了阻塞态,如 System.in, 但没有收到键盘的输入,则进入阻塞态。 5)线程礼让,Thread.yield()方法,暂停当前正在执行的线程对象,把执行机会 让给相同或更高优先级的线程,但并不会使线程进入阻塞态,线程仍处于可执

m0_67598977的博客 118

面试时我讲了“什么是线程安全”,面试官对我竖起了大拇指

不是线程的安全 面试官问:“什么是线程安全”,如果你不能很好的回答,那就请往下看吧。 论语中有句话叫“学而优则仕”,相信很多人都觉得是“学习好了可以做官”。然而,这样理解却是错的。切记望文生义。 同理,“线程安全”也不是指线程的安全,而是指内存的安全。为什么如此说呢?这和操作系统有关。 目前主流操作系统都是多任务的,即多个进程同时运行。为了保证安全,每个进程只能访问分配给自己的内存空间,而不能访问别的进程的,这是由操作系统保障的。 在每个进程的内存空间中都会有一块特殊的公共区域,通常称为堆(内存)。进程内的

资料qun832218493 145

JDBC之事务的封装和Threadlocal实例

一、什么是事务?          将多个操作当做一个原子操作来进行。(原子不可分割) 二、jdbc如何控制事务?          (1)jdbc在默认情况下自动提交事务,即一条sql语句执行后,立即提交事务。          (2)如果多个操作(即有多条sql语句要执行)要当做一个整理来执行,比如:在转账业务中需要执行两个sql,一个用来对账号进行扣除余额的操作(-1000),另一个

厚积而薄发,谋定而后动 1954

Java线程安全本质:JMM三大特性与实战避坑指南

线程安全是Java并发编程的基石概念,其核心在于理解Java内存模型(JMM)对原子性、可见性、有序性的底层约束。原子性保障操作不可分割,避免i++等复合操作的丢失更新;可见性确保线程间状态变更及时同步,依赖volatile或锁机制实现;有序性防止指令重排破坏逻辑时序,需借助happens-before规则校准。这些原理共同支撑着synchronized、ReentrantLock、AtomicInteger、ConcurrentHashMap等关键工具的选型与正确使用。在高并发Web服务、订单系统、配置中

315

面试官:Spring Bean 是线程安全的吗?

本文针对Java面试中常见的Spring Bean线程安全问题进行了深入解析。首先指出Spring默认单例Bean在多线程环境下存在共享状态的风险,通过代码示例展示了竞态条件的产生过程。然后提出四种解决方案:无状态设计、局部变量、同步机制和使用线程安全数据结构。文章还对比了单例和原型Bean的线程安全性差异,并给出了Controller层和Service层的实际应用建议。最后提供了面试答题策略,帮助开发者系统掌握这一核心面试知识点。

huazaijake的博客 381

后端开发—10个小技巧教你保证线程安全

对于从事后端开发的同学来说,线程安全问题是我们每天都需要考虑的问题。线程安全问题通俗的讲:主要是在多线程的环境下,不同线程同时读和写公共资源(临界资源),导致的数据异常问题。比如:变量a=0,线程1给该变量+1,线程2也给该变量+1。此时,线程3获取a的值有可能不是2,而是1。线程3这不就获取了错误的数据?线程安全问题会直接导致数据异常,从而影响业务功能的正常使用,所以这个问题还是非常严重的。那么,如何解决线程安全问题呢?今天跟大家一起聊聊,保证线程安全的10个小技巧,希望对你有所帮助。​我们都知道只有多个

Linuxhus的博客 397

讲义整理-并发安全

讲义整理-并发安全并发安全什么是线程安全性线程封闭无状态的类让类不可变volatile加锁和 CAS安全的发布TheadLocalServlet 辨析死锁概念现象、危害和解决现象危害解决其他安全问题活锁线程饥饿并发下的性能线程引入的开销上下文切换内存同步阻塞如何减少锁的竞争减少锁的粒度缩小锁的范围避免多余的锁锁分段替换独占锁线程安全的单例模式双重检查锁定解决之道懒汉式饿汉式 并发安全 什么是线程安全性 在《Java 并发编程实战》中,定义如下: 当多个线程访问某个类时,不管运行时环境采用何种调度方式或者这

Rick1024 241
上一篇: 线程的互斥与同步通信-笔记整理3
下一篇: 多个线程访问共享对象和数据的方式-笔记整理5
马克吐温
博客等级 码龄10年 11粉丝 43原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值