20200409 ThreadLocal

ThreadLocal,併發編程

ThreadLocal爲解決多線程程序的併發問題提供了一種新的思路。當使用ThreadLocal維護變量時,ThreadLocal爲每個使用該變量的線程提供獨立的變量副本,所以每一個線程都可以獨立地改變自己的副本,而不會影響其它線程所對應的副本。 

在ThreadLocal類中有一個Map,用於存儲每一個線程的變量副本,Map中元素的鍵爲線程對象,而值對應線程的變量副本。ThreadLocal中有四個方法: 

1、get()方法是用來獲取ThreadLocal在當前線程中保存的變量副本

2、set()用來設置當前線程中變量的副本

3、remove()用來移除當前線程中變量的副本

4、initialValue()是一個protected方法,顯然是爲了讓子類覆蓋而設計的,返回此線程局部變量的當前線程的初始值

 

初始時,在Thread裏面,threadLocals爲空,當通過ThreadLocal變量調用get()方法或者set()方法,就會對Thread類中的threadLocals進行初始化。

在進行get之前,必須先set,否則會報空指針異常;

 

很多情況下,ThreadLocal比直接使用synchronized同步機制解決線程安全問題更簡單,更方便,且結果程序擁有更高的併發性。

 

ThreadLocal的使用方法和實現原理。

ThreadLocal,很多地方叫做線程本地變量,也有些地方叫做線程本地存儲

出於線程安全的考慮,必須將這段代碼的兩個方法進行同步處理,並且在調用connect的地方需要進行同步處理。

一個線程不需要關心其他線程是否對這個connect進行了修改的。

get()方法是用來獲取ThreadLocal在當前線程中保存的變量副本,set()用來設置當前線程中變量的副本,remove()用來移除當前線程中變量的副本,initialValue()是一個protected方法,一般是用來在使用時進行重寫的,它是一個延遲加載方法。

內部維護了一個ThreadLocalMap。

 

1)實際的通過ThreadLocal創建的副本是存儲在每個線程自己的threadLocals中的;

2)爲何threadLocals的類型ThreadLocalMap的鍵值爲ThreadLocal對象,因爲每個線程中可有多個threadLocal變量,就像上面代碼中的longLocal和stringLocal;

3)在進行get之前,必須先set,否則會報空指針異常;

 

ThreadLocal是什麼

早在JDK 1.2的版本中就提供java.lang.ThreadLocal,ThreadLocal爲解決多線程程序的併發問題提供了一種新的思路。使用這個工具類可以很簡潔地編寫出優美的多線程程序。

當使用ThreadLocal維護變量時,ThreadLocal爲每個使用該變量的線程提供獨立的變量副本,所以每一個線程都可以獨立地改變自己的副本,而不會影響其它線程所對應的副本。

從線程的角度看,目標變量就象是線程的本地變量,這也是類名中“Local”所要表達的意思。

 

/**
 * Created on 2020/4/9 19:05
 * author:crs
 * Description: 測試ThreadLocal的使用
 */
public class TestThreadLocal {

    ThreadLocal intThread=  new ThreadLocal<Integer>();
    ThreadLocal strThread=  new ThreadLocal<String>();

   public void init(){
       //當前線程id和當前線程名稱
       intThread.set(Thread.currentThread().getId());
       strThread.set(Thread.currentThread().getName());
    }

    public Long getLong(){
       return (Long) intThread.get();
    }

    public String getString(){
        return (String) strThread.get();
    }

    public static void main(String[] args) throws InterruptedException {
        TestThreadLocal testThreadLocal = new TestThreadLocal();
        testThreadLocal.init();
        System.out.println(testThreadLocal.getLong());
        System.out.println(testThreadLocal.getString());
        System.out.println("--->");
        Thread thread = new Thread(){
            @Override
            public void run() {
                //設置當前子線程的id和名稱
                testThreadLocal.init();
                System.out.println(testThreadLocal.getLong());
                System.out.println(testThreadLocal.getString());
            }
        };
        thread.start();
        thread.join();
        System.out.println("------>");
        System.out.println(testThreadLocal.getLong());
        System.out.println(testThreadLocal.getString());
    }
}

 

 

 

 

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