线程中的ThreadLocal

ThreadLocal用于实现线程内的数据独立性,避免多线程环境下全局变量造成的冲突。每个线程调用ThreadLocal的set方法会将值存入对应线程的副本中,线程结束时可自动或手动释放内存。常应用于如数据库连接等需要线程内共享但又要避免相互干扰的场景。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

在多个线程交替执行的情况下,为了保证数据的独立性,我们可以使用局部变量,但是在进行不同方法或者不同类的调用时,局部变量未必好使,这时候就需要提升变量的作用范围,但问题也会随之而来。
例:

/*如下代码:
  主线程创建两个线程;
  每个线程获得一个随机数并赋值给全局变量data;
  并通过内部类A,B的get方法输出;*/
public class Test {

private static int data=0;

	public static void main(String[] args) {
		for (int i = 1; i <= 2; i++) {
			new Thread(new Runnable() {
	
				public void run() {
					int a=new Random().nextInt();
					System.out.println(a);
					data = a;
					System.out.println(Thread.currentThread().getName() + " has put data:" + data);
					new A().get();
					new B().get();
				}
			}).start();
		}  
	}
	
	static class A{
		public void get() {
			System.out.println("A from "+Thread.currentThread().getName()+" has get data:"+data);
		}
	}
	
	static class B{
		public void get() {
			System.out.println("B from "+Thread.currentThread().getName()+" has get data:"+data);
		}
	}
}

某次输出结果:
在这里插入图片描述
从输出我们可以直观的看出来:

  • 两个线程局部变量a为不同的随机数
  • 在执行输出data语句时两个线程data值就已经相同
  • A,B类在调用时获得值两线程相同

这并非普遍结果,但这次结果已经说明线程之间设置普通的全局变量时,会产生在使用完毕前被覆盖的问题,那么如何在这种状况下实现线程间数据的独立性呢?

ThreadLocal

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

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

ThreadLocal应用场景:
银行转账包含一些列操作:把转出账户的余额减少,把转入账户的余额增加,这两个操作要在同一个事务中完成,它们必须使用相同的数据库连接对象,转入和转出操作的代码分别是两个不同的账户对象的方法。

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

public class Test {

	static ThreadLocal<Integer> x = new ThreadLocal<Integer>();
	
	public static void main(String[] args) {
		for (int i = 1; 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);
					x.set(data);
					new A().get();
					new B().get();
				} 
			}).start();
		}  
	}
	
	static class A{
		public void get() {
			int data = x.get();
			System.out.println("A from "+Thread.currentThread().getName()+" has get data:"+data);
		}
	}
	
	static class B{
		public void get() {
			int data = x.get();
			System.out.println("B from "+Thread.currentThread().getName()+" has get data:"+data);
		}
	}
}

结果:
在这里插入图片描述
总结:

  • ThreadLocal和Synchronized都解决了多线程中相同变量的访问冲突问题
  • Synchronized通过让线程等待,牺牲时间来解决访问冲突
  • ThreadLocal通过每个线程单独一份存储空间,牺牲空间来解决冲突
  • ThreadLocal具有线程隔离的效果,只有在线程内才能获取到对应的值,线程外则不能访问到想要的值
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值