ThreadLocal實現在同一個線程內的數據共享

1、瞭解ThreadLocal類.

      查看相關api文檔,對該類描述如下:

      該類提供了線程局部變量。這些變量不同於它們的普通對應物,因爲訪問一個變量(通過其 getset 方法)的每個線程都有自己的局部變量,它獨立於變量的初始化副本。ThreadLocal 實例通常是類中的私有靜態字段,它們希望將狀態與某一個線程(例如,用戶 ID 或事務 ID)相關聯。

 

2、實驗目的:在不同模塊裏共享同一個變量的引用,爲了方便理解,你可以把不同的模塊理解爲不同的類,但模塊有更廣的概念.

     步驟:

     1、先定義一個自己的事務類MyTransaction,在該類中定義一個提交事務的方法commit();

     2、再定義一個自己的Session類MySession,在該類中定義一個beginTransaction方法和getTransaction方法,並定義一個ThreadLocal類的私有靜態字段.

     3、分別定義兩個模塊: A類各B類

     具體模擬代碼如下:

package test;
public class ThreadLocalTest {
	public static void main(String[] args) throws InterruptedException {
		final A a = new A();
		final B b = new B();
		for(int i=0;i<3;i++){
		new Thread(){
			public void run(){
				MySession session = new MySession(new MyTransaction());
				MyTransaction tx = session.beginTransaction();
				System.out.println("打開事務:"+tx);
				a.modify();
				b.save();
				tx.commit();//提交事務
				System.out.println();
			}	
		}.start();
		Thread.sleep(1000);
		}
	}
}	
	/**不同模塊共享同一個變量*/
	class A{
		public void modify(){
			System.out.println(Thread.currentThread()+": A 得到的事務: "+MySession.getTransaction());
		}
	}
	class B{
		public void save(){
			System.out.println(Thread.currentThread()+": B 得到的事務: "+MySession.getTransaction());
		}
	}
	
	class MyTransaction{
		public void commit(){
			System.out.println("提交事務:"+this);
		}
	}
	class MySession{
		private static MyTransaction transaction= null;
		private static ThreadLocal threadLocal = new ThreadLocal();
		public MySession(MyTransaction transaction){
			this.transaction = transaction;
		}
		public MyTransaction beginTransaction(){
			transaction = (MyTransaction)threadLocal.get();
			if(transaction==null){
				transaction = new MyTransaction();
				threadLocal.set(transaction);
			}
			return transaction;
		}
		public static MyTransaction getTransaction(){
			return (MyTransaction)threadLocal.get();
		}
	}

 

打印結果如下:

打開事務:test.MyTransaction@3e25a5
Thread[Thread-0,5,main]: A 得到的事務: test.MyTransaction@3e25a5
Thread[Thread-0,5,main]: B 得到的事務: test.MyTransaction@3e25a5
提交事務:test.MyTransaction@3e25a5

打開事務:test.MyTransaction@19821f
Thread[Thread-1,5,main]: A 得到的事務: test.MyTransaction@19821f
Thread[Thread-1,5,main]: B 得到的事務: test.MyTransaction@19821f
提交事務:test.MyTransaction@19821f

打開事務:test.MyTransaction@addbf1
Thread[Thread-2,5,main]: A 得到的事務: test.MyTransaction@addbf1
Thread[Thread-2,5,main]: B 得到的事務: test.MyTransaction@addbf1
提交事務:test.MyTransaction@addbf1

 3、ThreadLocal的應用場景

     1、如:銀行轉帳包含一系列操作:把轉出帳戶的餘額減少,把轉入帳戶的餘額增加,這兩個操作要在同一個事務中完成,它們必須使用相同的數據庫連接對象,轉入和轉出操作的代碼分別是兩個不同的帳戶對象的方法.

 

     2、又如:Struts2的ActionContex,同一段代碼被不同的線程調用運行時,該項代碼操作的數據是每個線程各自狀態和數據,對於不同的線程來說,getContext方法拿到的對象都不相同,對同一個線程來說,不管調用getContext方法多少次和哪個模塊getContext方法,拿到的都是同一個對象.

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章