成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

聊聊Java中的ThreadLocal作用

開發 前端
使用比較簡單,通過重載initialValue()這個方法進行初始化,或通過set進行設置,然后get使用即可,整個使用過程類似于HashMap。

在java中,如果我們多線程操作變量的時候,需要加上同步控制機制,原因是多線程操作一個變量,那么如果每個線程都操作自己線程的變量,那就不用加鎖了,也不用加同步控制了。

ThreadLocal就是這個作用,比如在Web開發中,我們用ThreadLocal來保存用戶信息,然后傳遞后臺多個service,然后每個線程單獨獲取自己的用戶信息;

初始化代碼也比較簡單:

public static ThreadLocal<SimpleDateFormat> dateFormatThreadLocal = new ThreadLocal<SimpleDateFormat>() {
@Override
protected SimpleDateFormat initialValue() {
return new SimpleDateFormat("mm:ss");
};

使用比較簡單,通過重載initialValue()這個方法進行初始化,或通過set進行設置,然后get使用即可,整個使用過程類似于HashMap。

那如何神奇的控制不同的線程保存不同的數據,從而達到線程的共享那,如下:

public T get() {
Thread t = Thread.currentThread();
ThreadLocalMap map = getMap(t);
if (map != null) {
ThreadLocalMap.Entry e = map.getEntry(this);
if (e != null) {
@SuppressWarnings("unchecked")
T result = (T)e.value;
return result;
}
}
return setInitialValue();
}

首先代碼中通過Thread.currentThread()來獲取當前的線程id,通過線程id獲取對應的ThreadLocalMap,這個getMap,其實是獲取Thread的成員變量如下:

ThreadLocalMap getMap(Thread t) {
return t.threadLocals;
}

此成員變量定義如下:

ThreadLocal.ThreadLocalMap threadLocals = null;

然后再來看這句話:

ThreadLocalMap.Entry e = map.getEntry(this);

即通過本ThreadLocal的對象作為key,獲取Entry對象后,再獲取它的value,如果為null那,那就調用setInitialValue()進行初始化,代碼如下:

private T setInitialValue() {
T value = initialValue();
Thread t = Thread.currentThread();
ThreadLocalMap map = getMap(t);
if (map != null)
map.set(this, value);
else
createMap(t, value);
return value;
}

此線程的map如果存在,不為null,直接更新,返回默認的初始化值,即initialValue()的返回值,如果不存在,則調用createMap(t,value);來創建map,如下:

void createMap(Thread t, T firstValue) {
t.threadLocals = new ThreadLocalMap(this, firstValue);
}

說實話代碼挺繞的,找了網上一張圖,會形成如下的結構:

【圖來自互聯網,侵權刪除】

我們從這個圖可以看到,ThreadLocal是所有線程的map的公共key,還要注意到,這個map比較特殊,是內部自己實現的,通過線性探測的方法來解決哈希沖突的,即如果槽位已經被占用了,則通過一個函數計算得到下一個槽位, 這種方法解決沖突的效率比較低,所以不建議用太多的ThreadLocal變量。

Threadlocal相關的數據結構:

【圖片來自互聯網,侵權刪除】

【圖片來自互聯網,侵權刪除】

從上圖中可以看到Entry繼承自弱應用,下次gc的時候會回收,但是只有key是弱引用,value還是強引用,下次gc的時候,key被回收而value可能一直不會被回收。

static class Entry extends WeakReference<ThreadLocal<?>> {
/** The value associated with this ThreadLocal. */
Object value;

Entry(ThreadLocal<?> k, Object v) {
super(k);
value = v;
}
}

所以解決辦法是,使用過之后記得通過remove()進行刪除。

總結:

ThreadLocal適用于無狀態的線程內變量共享的場景,比如我們說的通過ThreadLocal保存每個線程特有的信息,比如線程標識(打日志的時候適用,便于排查問題)。

ThreadLocal有一定的內存泄漏分享,記得要remove。

責任編輯:武曉燕 來源: 今日頭條
相關推薦

2021-07-01 07:34:08

NLP推薦系統

2021-12-11 19:00:54

Java中斷機制

2020-07-02 22:42:18

Java異常編程

2021-03-28 08:32:58

Java

2021-02-03 15:12:08

java內存溢出

2021-11-17 08:11:35

MySQL

2023-11-09 11:56:28

MySQL死鎖

2021-08-31 07:54:24

SQLDblink查詢

2024-04-26 00:00:00

Rust檢查器代碼

2016-08-31 15:50:50

PythonThreadLocal變量

2024-12-30 14:47:02

2020-09-26 07:19:46

Java

2023-08-02 08:54:58

Java弱引用鏈表

2022-05-11 07:36:12

Java線程安全

2022-12-06 08:12:11

Java關鍵字

2015-09-09 08:45:49

JavaThreadLocal

2021-10-30 19:56:10

Flutter按鈕 Buttons

2022-05-11 09:01:54

Swift類型系統幻象類型

2023-07-28 09:54:14

SQL數據Excel

2021-03-08 00:11:02

Spring注解開發
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 日韩中文在线视频 | av日日操 | 麻豆久久久9性大片 | 97精品超碰一区二区三区 | 欧美最猛黑人xxxⅹ 粉嫩一区二区三区四区公司1 | 国产综合久久 | 日韩欧美国产精品一区二区 | 欧美精品在线免费 | 中文字幕视频一区 | 欧美视频免费在线 | 国产精品久久网 | 在线亚洲一区 | 一区二区三区不卡视频 | 在线日韩 | 亚洲一区二区三区在线视频 | 欧美综合久久久 | 色综合中文 | 日韩中文字幕免费 | 精品免费国产视频 | 日韩免费福利视频 | 99精品欧美 | 成人国内精品久久久久一区 | 久久久精品 | 黄色片亚洲| 天天操天天干天天爽 | 国产精品九九 | 色必久久| 亚洲国产一区二区三区在线观看 | 风间由美一区二区三区在线观看 | 好好的日在线视频 | www.亚洲一区| 久久99视频免费观看 | 九九久久久久久 | 成人夜晚看av | 国产欧美视频一区二区 | 日韩伦理一区二区 | 成年免费在线观看 | 久久国产精品一区二区三区 | 国产午夜精品一区二区三区四区 | 国产成人精品久久二区二区 | 欧美日韩一 |