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方法)
應用場景
實現單個線程單例以及單個線程上下文信息存儲
實現線程安全,非線程安全的對象使用ThreadLocal之後就會變得線程安全,因爲每個線程都會有一個對應的實例(比如SimpleDateFormat不能直接用作靜態變量,線程不安全,但可以使用threadlocal將其改爲線程安全的來使用)
承載一些線程相關的數據,避免在方法中來回傳遞參數
示例代碼
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());
}
}