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變數
- Java中ThreadLocal的用法和原理Javathread
- 2.8.2 全域性資料服務GDS
- vue定義全域性變數和全域性方法Vue變數
- windows 資料夾檢視全域性生效Windows
- uni-app全域性資料傳遞APP
- Golang 全域性sql資料庫連線GolangSQL資料庫
- 全域性統一返回結果類
- javascript全域性變數的使用注意JavaScript變數
- 2.6.2 確定全域性資料庫名稱資料庫
- 從全域性視角看資料結構資料結構
- 全域性鎖和表鎖
- a標籤的使用,以及一些全域性屬性和連結型別。型別
- ThreadLocal的使用thread
- Yarn的安裝和全域性配置(源/快取位置/全域性安裝位置)Yarn快取
- elasticsearch + python 如何使用非全域性的 analyzerElasticsearchPython
- Java區域性變數與全域性變數Java變數
- 使用 MaxScale 實現資料庫的高可用性和彈性資料庫
- Laravel 使用 Elasticsearch 全域性搜尋LaravelElasticsearch
- less 全域性變數使用 引用變數
- MySQL 全域性表和表鎖MySql
- MySQL 全域性鎖和表鎖MySql
- 關於TornadoFx和Android的全域性配置工具類封裝實現及思路解析Android封裝
- ThreadLocal 原理和使用場景分析thread
- 分散式資料物件:超級終端的"全域性變數"分散式物件變數
- .NET Core如何全域性獲取使用者資訊?
- 區域性變數和全域性變數變數
- Python中的全域性變數和區域性變數Python變數
- 如何全域性的使用 Vagrant 命令啟動 Homestead
- Java ThreadLocal解析Javathread
- 面試中的 ThreadLocal 原理和使用場景面試thread
- java jdbc深入理解(connection與threadlocal與資料庫連線池和事務實)JavaJDBCthread資料庫
- 基礎篇:JAVA引用型別和ThreadLocalJava型別thread
- Java使用雪花演算法實現生成全域性唯一idJava演算法