java多執行緒——ThreadLocal

gary-liu發表於2017-03-18

ThreadLocal介紹

ThreadLocal可以建立只能由同一執行緒讀取和寫入的變數。因此,即使兩個執行緒正在執行相同的程式碼,並且程式碼具有對 ThreadLocal變數的引用,那麼這兩個執行緒不能看到對方的ThreadLocal變數。實際上ThreadLocal的值是放入了當前執行緒的一個ThreadLocalMap例項中,所以只能在本執行緒中訪問,其他執行緒無法訪問。

可以建立一個指定泛型型別的ThreadLocal物件,這樣我們就不需要每次使用get()方法返回的值做強制型別轉換。

ThreadLocal優勢

ThreadLocal並不是用來併發控制訪問一個共同物件,而是為了給每個執行緒分配一個只屬於該執行緒的物件,更準確的說是為了實現執行緒間的資料隔離。而ThreadLocal應用場景更多是想共享一個變數,但是該變數又不是執行緒安全的,那麼可以用ThreadLocal維護一個執行緒一個例項。有時候ThreadLocal也可以用來避免一些引數傳遞,通過ThreadLocal來訪問物件。

threadlocal 常用方法

1、public void set(T value):將值放入執行緒區域性變數中
2、public T get():從執行緒區域性變數中獲取值
3、public void remove():從執行緒區域性變數中移除值(有助於 JVM 垃圾回收)
4、protected T initialValue():返回執行緒區域性變數中的初始值(預設為 null,可以在新建物件時重寫initialValue方法)

應用場景

  1. 實現單個執行緒單例以及單個執行緒上下文資訊儲存

  2. 實現執行緒安全,非執行緒安全的物件使用ThreadLocal之後就會變得執行緒安全,因為每個執行緒都會有一個對應的例項(比如SimpleDateFormat不能直接用作靜態變數,執行緒不安全,但可以使用threadlocal將其改為執行緒安全的來使用)

  3. 承載一些執行緒相關的資料,避免在方法中來回傳遞引數

示例程式碼

public class ThreadLocalPractice {

    public static void main(String[] args){

        new Thread(new MyThread()).start();
        new Thread(new MyThread()).start();
    }
}

class MyThread implements Runnable{

    private ThreadLocal<Integer> threadLocal = new ThreadLocal<>();

    public void run(){
        threadLocal.set((int)(Math.random()*1000));

        try {
            Thread.sleep(500);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(Thread.currentThread().getName() + ": " + threadLocal.get());
    }
}

參考資料

Java ThreadLocal
理解Java中的ThreadLocal

相關文章