日韩无码专区无码一级三级片|91人人爱网站中日韩无码电影|厨房大战丰满熟妇|AV高清无码在线免费观看|另类AV日韩少妇熟女|中文日本大黄一级黄色片|色情在线视频免费|亚洲成人特黄a片|黄片wwwav色图欧美|欧亚乱色一区二区三区

RELATEED CONSULTING
相關(guān)咨詢
選擇下列產(chǎn)品馬上在線溝通
服務(wù)時(shí)間:8:30-17:00
你可能遇到了下面的問(wèn)題
關(guān)閉右側(cè)工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營(yíng)銷解決方案
聊聊Java中的ThreadLocal作用

ThreadLocal就是這個(gè)作用,比如在Web開(kāi)發(fā)中,我們用ThreadLocal來(lái)保存用戶信息,然后傳遞后臺(tái)多個(gè)service,然后每個(gè)線程單獨(dú)獲取自己的用戶信息;

初始化代碼也比較簡(jiǎn)單:

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

使用比較簡(jiǎn)單,通過(guò)重載initialValue()這個(gè)方法進(jìn)行初始化,或通過(guò)set進(jìn)行設(shè)置,然后get使用即可,整個(gè)使用過(guò)程類似于HashMap。

那如何神奇的控制不同的線程保存不同的數(shù)據(jù),從而達(dá)到線程的共享那,如下:

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();
}

首先代碼中通過(guò)Thread.currentThread()來(lái)獲取當(dāng)前的線程id,通過(guò)線程id獲取對(duì)應(yīng)的ThreadLocalMap,這個(gè)getMap,其實(shí)是獲取Thread的成員變量如下:

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

此成員變量定義如下:

ThreadLocal.ThreadLocalMap threadLocals = null;

然后再來(lái)看這句話:

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

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

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,直接更新,返回默認(rèn)的初始化值,即initialValue()的返回值,如果不存在,則調(diào)用createMap(t,value);來(lái)創(chuàng)建map,如下:

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

說(shuō)實(shí)話代碼挺繞的,找了網(wǎng)上一張圖,會(huì)形成如下的結(jié)構(gòu):

【圖來(lái)自互聯(lián)網(wǎng),侵權(quán)刪除】

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

Threadlocal相關(guān)的數(shù)據(jù)結(jié)構(gòu):

【圖片來(lái)自互聯(lián)網(wǎng),侵權(quán)刪除】

【圖片來(lái)自互聯(lián)網(wǎng),侵權(quán)刪除】

從上圖中可以看到Entry繼承自弱應(yīng)用,下次gc的時(shí)候會(huì)回收,但是只有key是弱引用,value還是強(qiáng)引用,下次gc的時(shí)候,key被回收而value可能一直不會(huì)被回收。

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

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

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

總結(jié):

ThreadLocal適用于無(wú)狀態(tài)的線程內(nèi)變量共享的場(chǎng)景,比如我們說(shuō)的通過(guò)ThreadLocal保存每個(gè)線程特有的信息,比如線程標(biāo)識(shí)(打日志的時(shí)候適用,便于排查問(wèn)題)。

ThreadLocal有一定的內(nèi)存泄漏分享,記得要remove。


網(wǎng)頁(yè)名稱:聊聊Java中的ThreadLocal作用
鏈接URL:http://www.5511xx.com/article/djsgpip.html