Java~“全域性資料盒“ --類ThreadLocal和InheritableThreadLocal的使用
ThreadLocal
- 類ThreadLocal主要解決的就是每個執行緒繫結自己的值,可以將ThreadLocal類比喻成全域性存放資料的盒子,盒子中可以儲存每個執行緒的私有資料。而這個盒子裡存放的資料是以map的形式將其對應的執行緒關聯起來.
get與set方法
- 首先看其原始碼
public T get() {
//獲取當前執行緒
Thread t = Thread.currentThread();
//在map中找到當前執行緒對應的map資料
ThreadLocalMap map = getMap(t);
if (map != null) {
//找到就獲取其鍵值對
ThreadLocalMap.Entry e = map.getEntry(this);
if (e != null) {
@SuppressWarnings("unchecked")
//返回鍵值對的value
T result = (T)e.value;
return result;
}
}
//返回預設值
return setInitialValue();
}
public void set(T value) {
//獲取當前執行緒
Thread t = Thread.currentThread();
//獲取當前執行緒的map
ThreadLocalMap map = getMap(t);
if (map != null)
map.set(this, value);
else
createMap(t, value);
}
- 演示
public static void main(String[] args) {
ThreadLocal threadLocal = new ThreadLocal();
if (threadLocal.get() == null) {
System.out.println("未設定值");
threadLocal.set("我是菜鳥");
}
System.out.println(threadLocal.get());
}
-
執行結果
-
從圖中的執行結果來看,第一次呼叫threadLocal 物件的get()方法時返回的值是null,通過呼叫set()方法賦值後順利取出值並列印到控制檯上。類Threadlocal解決的是變數在不同執行緒間的隔離性,也就是不同執行緒擁有自己的值,不同執行緒中的值是可以放入Threadlocal類中進行儲存的。
隔離性
- 雖然2個執行緒都向同一個threadlocal物件中set資料值,但每個執行緒還是能取出自己的資料。
public class Demo {
public static ThreadLocal<Date> threadLocal = new ThreadLocal<>();
public static void main(String[] args) throws InterruptedException {
//建立倆個執行緒去挨個儲存當前時間
Thread a = new Thread("A") {
@Override
public void run() {
for (int i = 0; i < 10; i++) {
threadLocal.set(new Date());
System.out.println(Thread.currentThread().getName() + " " + threadLocal.get().getTime());
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
};
Thread b = new Thread("B") {
@Override
public void run() {
for (int i = 0; i < 10; i++) {
threadLocal.set(new Date());
System.out.println(Thread.currentThread().getName() + " " + threadLocal.get().getTime());
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
};
a.start();
b.start();
a.join();
b.join();
}
}
覆蓋initialValue方法
- 在第一次呼叫Threadlocal類的get()方法返回值是null,怎麼樣實現第一次呼叫get()不返回null呢?也就是具有預設值的效果。就是重寫initialValue方法
public class Demo2 {
public static void main(String[] args) {
ThreadLocal threadLocal = new ThreadLocal() {
@Override
protected Object initialValue() {
return "我是預設值";
}
};
if (threadLocal.get() == null) {
System.out.println("未設定值");
threadLocal.set("我是菜鳥");
}
System.out.println(threadLocal.get());
}
}
類InheritableThreadLocal的使用
- 使用類InheritableThreadLocal可以在子執行緒中取得父執行緒繼承下來的值。
演示值繼承
public class Demo3 {
public static InheritableThreadLocal inheritableThreadLocal = new InheritableThreadLocal() {
@Override
protected Object initialValue() {
return new Date().getTime();
}
};
public static void main(String[] args) throws InterruptedException {
System.out.println("main get " + inheritableThreadLocal.get());
System.out.println("main set...");
Thread.sleep(222);
inheritableThreadLocal.set(new Date().getTime());
System.out.println("main get " + inheritableThreadLocal.get());
Thread thread = new Thread("A") {
@Override
public void run() {
for (int i = 0; i < 10; i++) {
System.out.println("A get " + inheritableThreadLocal.get());
try {
Thread.sleep(222);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
};
thread.start();
Thread.sleep(1000);
System.out.println("main 再次set...");
inheritableThreadLocal.set(new Date().getTime());
System.out.println("main get " + inheritableThreadLocal.get());
thread.join();
}
}
- 上述程式碼可以看出, 執行緒A繼承了主執行緒main的值, 而且當主執行緒將自己的資料修改後, A執行緒儲存的還是舊的那個值.
相關文章
- ThreadLocal及InheritableThreadLocal的原理剖析thread
- java高併發系列 - 第24天:ThreadLocal、InheritableThreadLocal(通俗易懂)Javathread
- Java - ThreadLocal類Javathread
- 【UniApp】-uni-app-全域性資料和區域性資料APP
- java 全域性變數和區域性變數Java變數
- node 全域性物件和全域性變數物件變數
- 2.8.2 全域性資料服務GDS
- vue定義全域性變數和全域性方法Vue變數
- 靜態全域性變數和全域性變數變數
- 分散式資料倉儲中,全域性和區域性資料倉儲有何區別?分散式
- Java中ThreadLocal的用法和原理Javathread
- Python的區域性變數和全域性變數使用解惑Python變數
- windows 資料夾檢視全域性生效Windows
- Golang 全域性sql資料庫連線GolangSQL資料庫
- uni-app全域性資料傳遞APP
- 全域性資料同步(三)終極方案
- 二、修改資料庫全域性名稱資料庫
- Java ThreadLocal 使用詳解Javathread
- angular中定義全域性變數及全域性變數的使用Angular變數
- 深入研究java.lang.ThreadLocal類Javathread
- Oracle全域性資料庫名、環境變數和sid的區別Oracle資料庫變數
- javascript全域性變數的使用注意JavaScript變數
- ThreadLocal在java web工程中的使用。threadJavaWeb
- 2.6.2 確定全域性資料庫名稱資料庫
- 從全域性視角看資料結構資料結構
- 全域性鎖和表鎖
- Python的全域性和區域性變數Python變數
- Yarn的安裝和全域性配置(源/快取位置/全域性安裝位置)Yarn快取
- 深入研究java.lang.ThreadLocal類薦Javathread
- a標籤的使用,以及一些全域性屬性和連結型別。型別
- 第 11 章 全域性屬性和其他
- Oracle分散式系統中的全域性資料庫名Oracle分散式資料庫
- 全域性索引和本地索引的比較索引
- navicat資料庫全域性關係視覺化資料庫視覺化
- 【全域性資料庫名、連線描述符】資料庫
- java全域性滑鼠鍵盤監聽Java
- MySQL 全域性鎖和表鎖MySql
- Oracle全域性索引和本地索引Oracle索引