??JVM運行時數據區(qū)分為線程共享部分、線程獨占部分。多線程程訪問共享可變數據時下翎,涉及到線程間數據同步的問題。但并不是所有時候都要用到共享數據宝当,所以線程封閉概念就提出來了视事。
數據都被封閉在各自的線程之中,就不需要同步庆揩,這種通過將數據封閉在線程中而避免使用同步的技術稱為線程封閉俐东。
??線程封閉具體的體現有:
- 棧封閉(局部變量)
- ThreadLocal類
棧封閉
??棧封閉是我們編程當中遇到的最多的線程封閉。其實就是局部變量盾鳞。多個線程訪問一個方法犬性,此方法中的局部變量都會被拷貝一分兒到線程棧中瞻离。編譯時在虛擬機棧中存儲腾仅,虛擬機棧是線程獨享的,所以局部變量是不被多個線程所共享的套利,也就不會出現并發(fā)問題推励。
ThreadLocal封閉
??ThreadLocal類是JDK提供的一種特殊的變量。它是一個線程級別變量肉迫,每個線程都有一個ThreadLocal验辞,即每個線程都擁用了自己獨立的一個變量,這個類能防止線程內的可變變量的共享喊衫,通過ThreadLocal類可保證線程特有的變量封閉在線程內而不會逸出到該線程外跌造。
用法: ThreadLocal<T> var = new ThreadLocal<T>();
會自動在每個線程上創(chuàng)建一個T的副本,副本之間彼此獨立,互不影響壳贪×暾洌可以用ThreadLocal存儲一些參數,以便在線程中多個方法中使用违施,用來代替方法傳參的做法互纯。
代碼示列
/** 線程封閉示例 */
public class Demo {
/** threadLocal變量,每個線程都有一個副本磕蒲,互不干擾 */
public static ThreadLocal<String> value = new ThreadLocal<>();
/**
* threadlocal測試
*
* @throws Exception
*/
public void threadLocalTest() throws Exception {
// threadlocal線程封閉示例
value.set("這是主線程設置的MainThreadTest"); // 主線程設置值
String v = value.get();
System.out.println("線程1執(zhí)行之前留潦,主線程取到的值:" + v);
new Thread(new Runnable() {
@Override
public void run() {
String v = value.get();
System.out.println("線程1取到的值:" + v);
// 設置 threadLocal
value.set("這是線程1設置的Thread1");
v = value.get();
System.out.println("重新設置之后,線程1取到的值:" + v);
System.out.println("線程1執(zhí)行結束");
}
}).start();
Thread.sleep(5000L); // 等待所有線程執(zhí)行結束
v = value.get();
System.out.println("線程1執(zhí)行之后辣往,主線程取到的值:" + v);
}
public static void main(String[] args) throws Exception {
new Demo().threadLocalTest();
}
}
運行結果如下:
線程1執(zhí)行之前兔院,主線程取到的值:這是主線程設置的MainThreadTest
線程1取到的值:null
重新設置之后,線程1取到的值:這是線程1設置的Thread1
線程1執(zhí)行結束
線程1執(zhí)行之后排吴,主線程取到的值:這是主線程設置的MainThreadTest
??從運行結果可以看出秆乳,在主線程中給賦的值,子線程獲取不到钻哩。子線程中賦的值屹堰,主線程也獲取不到。這個值對線程是獨立的,每個線程都擁用了自己獨立的一個變量街氢,互不影響扯键。