Java併發程式設計 看不懂算我的!
ThreadLocal是什麼
ThreadLocal是什麼呢?其實ThreadLocal並非是一個執行緒的本地實現版本,它並不是一個Thread,而是threadlocalvariable(執行緒區域性變數)。也許把它命名為ThreadLocalVar更加合適。ThreadLocal功能非常簡單,就是為每一個使用該變數的執行緒都提供一個變數值的副本,是Java中一種較為特殊的執行緒繫結機制,是每一個執行緒都可以獨立地改變自己的副本,而不會和其它執行緒的副本衝突。
從執行緒的角度看,每個執行緒都保持一個對其執行緒區域性變數副本的隱式引用,只要執行緒是活動的並且ThreadLocal例項是可訪問的;線上程消失之後,其執行緒區域性例項的所有副本都會被垃圾回收(除非存在對這些副本的其他引用)。
通過ThreadLocal存取的資料,總是與當前執行緒相關,也就是說,JVM 為每個執行的執行緒,綁定了私有的本地例項存取空間,從而為多執行緒環境常出現的併發訪問問題提供了一種隔離機制。
相信這裡有很多學習java的朋友,小編整理了一份java方面的學習資料,
有想要學習java的可以加一下我的學習群的喲,60833,4068,歡迎愛學習java的你們!
ThreadLocal的介面方法
void set(Object value)
設定當前執行緒的執行緒區域性變數的值;
public Object get()
該方法返回當前執行緒所對應的執行緒區域性變數;
public void remove()
將當前執行緒區域性變數的值刪除,目的是為了減少記憶體的佔用,該方法是JDK 5.0新增的方法。需要指出的是,當執行緒結束後,對應該執行緒的區域性變數將自動被垃圾回收,所以顯式呼叫該方法清除執行緒的區域性變數並不是必須的操作,但它可以加快記憶體回收的速度;
protected Object initialValue()
返回該執行緒區域性變數的初始值,該方法是一個protected的方法,顯然是為了讓子類覆蓋而設計的。這個方法是一個延遲呼叫方法,線上程第1次呼叫get()或set(Object)時才執行,並且僅執行1次。ThreadLocal中的預設實現直接返回一個null
這裡注意,ThreadLocal中是有一個Map,但這個Map不是我們平時使用的Map,而是ThreadLocalMap,ThreadLocalMap是ThreadLocal的一個內部類,不對外使用的。當使用ThreadLocal存值時,首先是獲取到當前執行緒物件,然後獲取到當前執行緒本地變數Map,最後將當前使用的ThreadLocal和傳入的值放到Map中,也就是說ThreadLocalMap中存的值是[ThreadLocal物件, 存放的值],這樣做的好處是,每個執行緒都對應一個本地變數的Map,所以一個執行緒可以存在多個執行緒本地變數。
一個TheadLocal例項
/**
*
* @ClassName: SequenceNumber
* @author xingle
* @date 2015-3-9 上午9:54:23
*/
public class SequenceNumber {
//①通過匿名內部類覆蓋ThreadLocal的initialValue()方法,指定初始值
private static ThreadLocal<Integer> seqNum = new ThreadLocal<Integer>(){
public Integer initialValue(){
return 0;
}
};
//②獲取下一個序列值
public int getNextNum(){
seqNum.set(seqNum.get()+1);
return seqNum.get();
}
public static void main(String[] args){
SequenceNumber sn = new SequenceNumber();
//③ 3個執行緒共享sn,各自產生序列號
TestClient t1 = new TestClient(sn);
TestClient t2 = new TestClient(sn);
TestClient t3 = new TestClient(sn);
t1.start();
t2.start();
t3.start();
}
private static class TestClient extends Thread{
private SequenceNumber sn;
public TestClient(SequenceNumber sn){
this.sn = sn;
}
public void run(){
//④每個執行緒打出3個序列值
for (int i = 0 ;i<3;i++){
System.out.println("thread["+Thread.currentThread().getName()+"] sn["+sn.getNextNum()+"]");
}
}
}
}
通常我們通過匿名內部類的方式定義ThreadLocal的子類,提供初始的變數值,如①處所示。TestClient執行緒產生一組序列號,在③處,我們生成3個TestClient,它們共享同一個SequenceNumber例項。執行以上程式碼,在控制檯上輸出以下的結果:
每個執行緒所產生的序號雖然都共享同一個Sequence Number例項,但它們並沒有發生相互干擾的情況,而是各自產生獨立的序列號,這是因為我們通過ThreadLocal為每一個執行緒提供了單獨的副本。
歡迎關注胖胖程式設計師,視覺化學習java,每天更新文章,讓Java學習更加簡單。