ThreadLocal实现线程范围内共享变量和对象



既然ThreadLocal类为每一个使用该变量的线程都提供了一个变量值的副本,使每一个线程都可以独立地改变自己的副本,而不会和其他线程的副本冲突,好像每一个线程都完全拥有该变量。那么在同一个线程内,各个模块就可以共享变量并且不会和其他线程的变量产生冲突。

例如线程1运行时会调用A、B、C三个模块\对象,这三个模块\对象会访问一个相同变量x;同样线程2运行时也会调用A、B、C三个模块\对象,这三个模块\对象也会访问一个相同变量x。如果这个变量是普通的静态变量,那么无论哪个线程的哪个模块\对象访问,都可以改变该变量的值并且在其他线程的模块\对象访问时访问到的是被改变后的值。如果将x定义为ThreadLocal类的对象,那么线程1和线程2都会保留一个变量x的副本,它们相互之间不会冲突,这样就实现了线程范围内共享变量。



见下面程序
首先定义一个数据共享类,其中count要被多个模块访问
//定义一个数据共享类,其中count要被多个模块访问
class ShareData {
	
	//将count定义为ThreadLocal类型
	//以便在线程范围内实现共享
	private ThreadLocal<Integer> count = new ThreadLocal<Integer>();
	
	public void setCount(int i){
		//自动装箱
		count.set(i);
	}
	
	public int getCount(){
		//自动拆箱
		return count.get();
	}
}

在ThreadShareData类中开启两个线程,每个线程都有两个内部类使用count
public class ThreadShareData {

	//创建一个ShareData对象,这个对象被两个线程使用
	private static ShareData data = new ShareData();
	
	public static void main(String[] args) {
		// TODO Auto-generated method stub

		//使用循环开启两个线程
		for(int i = 0; i < 2; i++){
			new Thread(){
				public void run() {
					//为ShareData的count赋值
					int count = new Random().nextInt();
					data.setCount(count);
					System.out.println(Thread.currentThread().getName() 
							+ "--已为count赋值,值为" + count);
					new A(data).show();
					new B(data).show();
				}
			}.start();
		}
		
	}
	
	//内部类模块A
	static class A{
		
		private ShareData data;
		
		public A(ShareData data){
			this.data = data;
		}
		//访问count
		public void show(){
			System.out.println("线程:" + Thread.currentThread().getName() + 
					"--A模块count值" + data.getCount());
		}
	}
	
	//内部类模块B
	static class B{
		
		private ShareData data;
		
		public B(ShareData data){
			this.data = data;
		}
		//访问count
		public void show(){
			System.out.println("线程:" + Thread.currentThread().getName() + 
					"--B模块count值" + data.getCount());
		}
	}

}

运行

两个线程用到同一个ShareData对象,但是每个线程中的count值不同,但同一个线程中每个模块使用count值相同。这样通过使用ThreadLocal就实现了线程范围内的共享变量。


一个ThreadLocal代表一个变量,故其中只能放一个数据。如果有n个变量都要线程范围内共享,则要定义n个ThreadLocal对象,或者将n个变量封装到一个实体对象中。

使用ThreadLocal可以在线程范围内共享变量,也可以共享对象。要想在线程范围内共享对象,该类的设计与单例类有些类似。

定义一个对象共享类,在线程范围内共享对象
//定义一个对象共享类,在线程范围内共享对象
class ShareInstance {
	
	//名称和id号
	private String name;
	private int id;
	
	//使用ThreadLocal,存储线程内共享的对象
	private static ThreadLocal<ShareInstance> map = new ThreadLocal<ShareInstance>();
	
	//构造器私有化
	private ShareInstance(){}
	
	//提供静态方法获取对象
	public static ShareInstance getInstance(){
		ShareInstance instance = map.get();
		if(instance == null){
			instance = new ShareInstance();
			map.set(instance);
		}
		return instance;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public int getId() {
		return id;
	}
	public void setId(int id) {
		this.id = id;
	}
}

ThreadShareInstance类中开启两个线程,每个线程都有两个内部类使用ShareInstance对象
public class ThreadShareInstance {
	
	public static void main(String[] args) {
		// TODO Auto-generated method stub

		//使用循环开启两个线程
		for(int i = 0; i < 2; i++){
			new Thread(){
				public void run() {
					ShareInstance instance = ShareInstance.getInstance();
					//为ShareInstance的name和id赋值
					int id = new Random().nextInt();
					instance.setName("name");
					instance.setId(id);
					System.out.println(Thread.currentThread().getName() 
							+ "--已为id赋值,值为" + id);
					new A().show();
					new B().show();
				}
			}.start();
		}
		
	}
	
	//内部类模块A
	static class A{

		//访问instance
		public void show(){
			ShareInstance instance = ShareInstance.getInstance();
			System.out.println("线程:" + Thread.currentThread().getName() + 
					"--A模块name值为:" + instance.getName() + ",id值为:" + instance.getId());
		}
	}
	
	//内部类模块B
	static class B{

		//访问instance
		public void show(){
			ShareInstance instance = ShareInstance.getInstance();
			System.out.println("线程:" + Thread.currentThread().getName() + 
					"--B模块name值为:" + instance.getName() + ",id值为:" + instance.getId());
		}
	}

}

运行程序


三个模块:内部类A和B,主方法中都有一个ShareInstance对象,在同一个线程中,他们是同一个对象;而不同线程中是不同对象。
通过使用ThreadLocal设计ShareInstance类,就可以在线程范围内共享对象而在不同线程中使用不同对象。


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值