日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程语言 > java >内容正文

java

java threadlocal 缺点_Java的ThreadLocal如何在后台实现?

發(fā)布時間:2023/12/3 java 28 豆豆
生活随笔 收集整理的這篇文章主要介紹了 java threadlocal 缺点_Java的ThreadLocal如何在后台实现? 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

小編典典

這里的所有答案都是正確的,但是有些令人失望,因為它們多少掩蓋了聰明ThreadLocal的實現(xiàn)是多么的明智。我只是在尋找源代碼,ThreadLocal并且對它的實現(xiàn)方式印象深刻。

天真的實現(xiàn)

如果我要求您ThreadLocal在javadoc中描述的給定API的基礎(chǔ)上實現(xiàn)一個類,該怎么辦?最初的實現(xiàn)可能是ConcurrentHashMap使用Thread.currentThread()作為其密鑰。這樣會很好地工作,但確實有一些缺點。

線程爭用- ConcurrentHashMap是一個非常聰明的類,但是它最終仍必須處理防止多個線程以任何方式破壞它,并且如果不同的線程有規(guī)律地命中它,將會降低速度。

即使在線程完成并且可以進行GC處理后,它仍永久保持指向線程和對象的指針。

GC友好的實現(xiàn)

好的,再試一次,讓我們使用弱引用來處理垃圾回收問題。處理WeakReferences可能會造成混淆,但是使用像這樣構(gòu)建的地圖應(yīng)該足夠了:

Collections.synchronizedMap(new WeakHashMap())

或者,如果我們使用的是番石榴(應(yīng)該是!):

new MapMaker().weakKeys().makeMap()

這意味著一旦沒有其他人抓住線程(暗示線程已完成),就可以對鍵/值進行垃圾收集,這是一種改進,但仍無法解決線程爭用問題,這意味著到目前為止,我們ThreadLocal還不是全部令人贊嘆的一堂課。此外,如果有人決定在Thread完成后保留對象,那么就永遠不會對它們進行GC處理,因此即使我們的對象現(xiàn)在在技術(shù)上無法到達,也不會對其進行GC處理。

聰明的實現(xiàn)

我們一直在考慮ThreadLocal將線程映射為值,但是也許這實際上并不是正確的思考方式。與其將其視為從Threads到每個ThreadLocal對象中的值的映射,不如將其視為ThreadLocal對象到

每個Thread中的

值的映射怎么辦?如果每個線程都存儲了該映射,而ThreadLocal僅提供了該映射的一個不錯的接口,我們可以避免以前實現(xiàn)中的所有問題。

一個實現(xiàn)看起來像這樣:

// called for each thread, and updated by the ThreadLocal instance

new WeakHashMap()

此處無需擔(dān)心并發(fā)性,因為只有一個線程將訪問此映射。

Java開發(fā)人員在這里比我們有一個主要優(yōu)勢-他們可以直接開發(fā)Thread類并向其添加字段和操作,而這正是他們所做的。

/* ThreadLocal values pertaining to this thread. This map is maintained

* by the ThreadLocal class. */

ThreadLocal.ThreadLocalMap threadLocals = null;

正如評論所暗示的,確實是ThreadLocal對象為此跟蹤的所有值的私有包映射Thread。的實現(xiàn)ThreadLocalMap不是WeakHashMap,而是遵循相同的基本協(xié)定,包括通過弱引用來持有其密鑰。

ThreadLocal.get() 然后實現(xiàn)如下:

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

}

而ThreadLocal.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;

}

本質(zhì)上, 在此線程中

使用地圖可以容納我們所有的ThreadLocal對象。這樣,我們永遠不必擔(dān)心其他線程中的值(ThreadLocal字面上只能訪問當(dāng)前線程中的值),因此沒有并發(fā)問題。此外,一旦Thread完成,其映射將自動進行GC處理,并且將清除所有本地對象。即使將Thread其保留,ThreadLocal對象也會被弱引用保留,并且一旦ThreadLocal對象超出范圍,就可以將其清除。

不用說,這個實現(xiàn)給我留下了深刻的印象,它很好地解決了很多并發(fā)問題(可以利用作為核心Java的一部分,但這是可以原諒的,因為它是一個非常聰明的類),并且允許快速和對僅一次需要一個線程訪問的對象的線程安全訪問。

tl; dr ThreadLocal的實現(xiàn)非常酷,并且比您乍看之下要快/聰明得多。

如果您喜歡這個答案,您可能也會喜歡我(不那么詳細)的討論ThreadLocalRandom。

2020-09-15

總結(jié)

以上是生活随笔為你收集整理的java threadlocal 缺点_Java的ThreadLocal如何在后台实现?的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。