1、瞭解ThreadLocal類.
查看相關api文檔,對該類描述如下:
該類提供了線程局部變量。這些變量不同於它們的普通對應物,因爲訪問一個變量(通過其 get 或 set 方法)的每個線程都有自己的局部變量,它獨立於變量的初始化副本。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方法,拿到的都是同一個對象.