1. ThreadLocal概述
1.ThreadLocal提供線程局部變量;開箱即用開銷小,可以代替多線程訪問共享變量時需要上鎖的需要。
在各種涉及的多線程語言都有,Java用哈希表表實現(ThreadLocalMap)
3.實現原理
2. 基本API
1.構造函數ThreadLocal()
2.初始化 initialValue()
只有線程在第一次調用get方法時,執行此方法。
3.訪問器 get/set
public T get(),返回ThreadLocal中當前線程副本的值。變量第一次get時沒有當前線程的值,就調用initilaVaule()的返回值。
4.回收 remove
以下手動來個demo(涉及到延遲加載)
//用泛型構造器賦初始值
public static ThreadLocal<Long> x = new ThreadLocal<>(){
@Override
protected Long initialValue() {
System.out.println("Initial Value run...");
return Thread.currentThread().getId(); //拿到當前線程ID
}
};
public static void main(String[] argv){
new Thread(){
@Override
public void run(){
System.out.println(x.get());
}
}.start();
System.out.println(x.get());
}
}
結果是:(main函數中兩個不同get都各調用了一次InitialValue方法,每個線程都有自己的變量值)
下面是測試set方法:
public class APItests {
public static ThreadLocal<Long> threadLocal = new ThreadLocal<Long>(){
@Override
protected Long initialValue() {
System.out.println("Initial Value run...");
return Thread.currentThread().getId();
}
};
public static void main(String[] argv) {
new Thread() {
@Override
public void run() {
System.out.println(threadLocal.get());
}
}.start();
threadLocal.set(6l);
System.out.println(threadLocal.get());
}
}
得到的結果如下:可見InitialValue只調用了一次
3. ThreadLocal使用場景
- 1.線程安全
- 2.線程資源一致
基於線程池模型去Sychronized很危險:排隊去鎖消耗的時間導致CPU用不完
eg:線程池中24個線程,打來100個併發量,一次只能24個,而用ThreadLocal收集數據很快且安全。
同一個事務下的任務們必須保證原子性,也就是說下圖中的Task們都須通過同一個線程的getConnection()方法拿到完全相同的數據。首先判斷ThreadLocalMap中是否存在所需值,如果沒有就去連接池取,取到的值先存到線程共享的ThreadLocalMap中,再返回給對應Task。
(3)併發計算
常見於分佈式計算,一臺機器多核並行