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

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

 

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

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

3.ThreadLocal的应用场景:

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

       (2)例如Strut2ActionContext,同一段代码被不同的线程调用运行时,该代码操作的数据是每个线程各自的状态和数据,对于不同的线程来说,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;
		}
	 }
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值