AVt天堂网 手机版,亚洲va久久久噜噜噜久久4399,天天综合亚洲色在线精品,亚洲一级Av无码毛片久久精品

當(dāng)前位置:首頁 > 科技  > 軟件

京東二面:為什么Netty要創(chuàng)造FastThreadLocal?

來源: 責(zé)編: 時間:2024-05-29 08:58:42 141觀看
導(dǎo)讀FastThreadLocal 從字面意義上來看,它是“Fast”+“ThreadLocal”的結(jié)合體,寓意為快速的 ThreadLocal。那么,問題來了,Netty 為什么要再造一個 FastThreadLocal?FastThreadLocal 運行快的原因是啥?除了快之外,它還有其他優(yōu)勢

uKY28資訊網(wǎng)——每日最新資訊28at.com

FastThreadLocal 從字面意義上來看,它是“Fast”+“ThreadLocal”的結(jié)合體,寓意為快速的 ThreadLocal。那么,問題來了,Netty 為什么要再造一個 FastThreadLocal?FastThreadLocal 運行快的原因是啥?除了快之外,它還有其他優(yōu)勢嗎?uKY28資訊網(wǎng)——每日最新資訊28at.com

1.先從ThreadLocal說起

ThreadLocal 線程本地變量,每個線程都擁有一份該變量的獨立副本,即使是在多線程環(huán)境下,每個線程也只能修改和訪問自己的那份副本,從而避免了線程安全問題,實現(xiàn)了線程間的隔離。uKY28資訊網(wǎng)——每日最新資訊28at.com

ThreadLocal 底層是使用 ThreadLocalMap 實現(xiàn)的,這點從 JDK 的源碼中可以看出,核心源碼如下:uKY28資訊網(wǎng)——每日最新資訊28at.com

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

從 ThreadLocal 的 set 方法可以看出,ThreadLocal 是存儲在 ThreadLocalMap 中的,咱們繼續(xù)看 ThreadLocalMap 的源碼實現(xiàn):uKY28資訊網(wǎng)——每日最新資訊28at.com

uKY28資訊網(wǎng)——每日最新資訊28at.com

從上面源碼可以看出,ThreadLocalMap 中存放的是 Entry(哈希桶),而 Entry 中的 key 就是 ThreadLocal,而 value 則是要存儲的值,所以我們得出 ThreadLocal 的底層實現(xiàn)如下:uKY28資訊網(wǎng)——每日最新資訊28at.com

uKY28資訊網(wǎng)——每日最新資訊28at.com

2.ThreadLocal存在的問題

(1)性能問題

因為 ThreadLocal 底層是使用 ThreadLocalMap 實現(xiàn)的,ThreadLocalMap 類似于哈希表。當(dāng)一個線程是擁有多個 ThreadLocal 時,ThreadLocalMap 很容易發(fā)生 Hash 沖突,此時 ThreadLocal 就不得不使用線性探測法來解決哈希沖突了,而在解決 Hash 沖突時需要不停地向下尋找,效率較低,因此 ThreadLocal 存在的第一個問題就是性能較低。uKY28資訊網(wǎng)——每日最新資訊28at.com

(2)內(nèi)存泄漏問題

ThreadLocal 也存在內(nèi)存泄漏的問題,具體來說 ThreadLocalMap 使用 ThreadLocal 對象作為鍵(Key),并且這個鍵是弱引用(WeakReference)類型。這意味著當(dāng)沒有其他強(qiáng)引用指向 ThreadLocal 對象時,它將會在下次垃圾回收時被回收。然而,Entry 中保存的值(Value)仍然是強(qiáng)引用,這就可能導(dǎo)致以下問題:uKY28資訊網(wǎng)——每日最新資訊28at.com

  • 弱引用鍵的回收:一旦外部對 ThreadLocal 實例的所有強(qiáng)引用消失,ThreadLocal 對象本身就會變?yōu)槿蹩蛇_(dá)狀態(tài)。在下一次垃圾回收時,由于是弱引用,ThreadLocal 對象會被回收,但 Entry 中的 Value(即實際存儲的數(shù)據(jù))仍然是強(qiáng)引用,因此不會被回收。
  • Map 引用陷阱:即使 ThreadLocal 鍵被回收,Entry 仍然存在于 ThreadLocalMap 中,并且由于 Map 對 Entry 的引用,這些 Entry 所持有的 Value 對象也不會被垃圾回收,從而導(dǎo)致這些對象無法被使用也無法被釋放,形成了所謂的“內(nèi)存泄漏”。
  • 線程長期存活:在一些場景下,特別是使用線程池時,線程的生命周期往往很長,甚至伴隨整個應(yīng)用的生命周期。這意味著 ThreadLocalMap 中的 Entry 可能會長時間不被清理,進(jìn)一步加劇了內(nèi)存泄漏問題。

所以,綜合來看,在使用 ThreadLocal 時,如果在使用完之后,未及時調(diào)用 remove() 方法的話,就會出現(xiàn)內(nèi)存泄漏的問題。uKY28資訊網(wǎng)——每日最新資訊28at.com

3.FastThreadLocal特點

為了解決 ThreadLocal 存在的這些問題,所以 Netty 創(chuàng)造出了一個 FastThreadLocal,F(xiàn)astThreadLocal 的特點如下。uKY28資訊網(wǎng)——每日最新資訊28at.com

(1)效率高

FastThreadLocal 之所以性能高的原因是因為其存儲結(jié)構(gòu),在 FastThreadLocal 中并沒有向 ThreadLocal 那樣,使用哈希表來存儲元素,而是使用了數(shù)組來進(jìn)行元素存儲,它的核心實現(xiàn)源碼如下:uKY28資訊網(wǎng)——每日最新資訊28at.com

public class FastThreadLocal<V> {    // FastThreadLocal中的index是記錄了該它維護(hù)的數(shù)據(jù)應(yīng)該存儲的位置    // InternalThreadLocalMap數(shù)組中的下標(biāo), 它是在構(gòu)造函數(shù)中確定的    private final int index;     public InternalThreadLocal() {        index = InternalThreadLocalMap.nextVariableIndex();    }    // 省略其他代碼}

FastThreadLocal 核心類 InternalThreadLocalMap 的實現(xiàn)源碼如下:uKY28資訊網(wǎng)——每日最新資訊28at.com

public final class InternalThreadLocalMap extends UnpaddedInternalThreadLocalMap {    // 自增索引, ?于計算下次存儲到Object數(shù)組中的位置    private static final AtomicInteger nextIndex = new AtomicInteger();     private static final int ARRAY_LIST_CAPACITY_MAX_SIZE = Integer.MAX_VALUE - 8;     public static int nextVariableIndex() {        int index = nextIndex.getAndIncrement();        if (index >= ARRAY_LIST_CAPACITY_MAX_SIZE || index < 0) {            nextIndex.set(ARRAY_LIST_CAPACITY_MAX_SIZE);            throw new IllegalStateException("too many thread-local indexed variables");        }        return index;    }    // 省略其他代碼}

從上述源碼可以看出,F(xiàn)astThreadLocal 在初始化的時候分配一個數(shù)組索引 index,index 的值采用原子類 AtomicInteger 保證順序遞增,通過調(diào)用 InternalThreadLocalMap.nextVariableIndex() 方法獲得。然后在讀寫數(shù)據(jù)的時候通過數(shù)組下標(biāo) index 直接定位到 FastThreadLocal 的位置,時間復(fù)雜度為 O(1)。如果數(shù)組下標(biāo)遞增到非常大,那么數(shù)組也會比較大,所以 FastThreadLocal 是通過空間換時間的思想提升讀寫性能。uKY28資訊網(wǎng)——每日最新資訊28at.com

因此,在 FastThreadLocal 中并不需要使用線性探測法來解決 Hash 沖突,因為它是使用數(shù)組進(jìn)行存儲的,每次使用下標(biāo)進(jìn)行查詢即可,它的查詢時間復(fù)雜度也是 O(1) 的,所以它的操作效率很高。uKY28資訊網(wǎng)——每日最新資訊28at.com

(2)安全性更高

JDK 原生的 ThreadLocal 使用不當(dāng)可能造成內(nèi)存泄漏,只能等待線程銷毀。然而 FastThreadLocal 卻不存在這個問題,在 FastThreadLocal 中不僅提供了 remove() 方法可以主動清除對象,而且它還封裝了 FastThreadLocalRunnable,F(xiàn)astThreadLocalRunnable 在最后使用完之后會自動調(diào)用 removeAll() 方法將集合中所有對象清理掉,因此 FastThreadLocal 更安全。uKY28資訊網(wǎng)——每日最新資訊28at.com

FastThreadLocalRunnable 自動清除對象的實現(xiàn)核心源碼如下:uKY28資訊網(wǎng)——每日最新資訊28at.com

final class FastThreadLocalRunnable implements Runnable {    private final Runnable runnable;    @Override    public void run() {        try {            runnable.run();        } finally {            FastThreadLocal.removeAll();        }    }    static Runnable wrap(Runnable runnable) {        return runnable instanceof FastThreadLocalRunnable                 ? runnable : new FastThreadLocalRunnable(runnable);    }}

4.小結(jié)

FastThreadLocal 相比于 ThreadLocal 存在以下兩個主要優(yōu)點:uKY28資訊網(wǎng)——每日最新資訊28at.com

  • 性能更高:FastThreadLocal 使用了數(shù)組的方式來存儲元素,所以它的查詢時間復(fù)雜度 O(1) 相比于 ThreadLocal 的哈希表操作效率更高。
  • 安全性更高:FastThreadLocal 中的 FastThreadLocalRunnable 在最后執(zhí)行完之后會自動調(diào)用 removeAll() 將集合中所有對象都清理掉,可以避免內(nèi)存泄漏的問題,所以它的安全性更高。

本文鏈接:http://www.tebozhan.com/showinfo-26-91377-0.html京東二面:為什么Netty要創(chuàng)造FastThreadLocal?

聲明:本網(wǎng)頁內(nèi)容旨在傳播知識,若有侵權(quán)等問題請及時與本網(wǎng)聯(lián)系,我們將在第一時間刪除處理。郵件:2376512515@qq.com

上一篇: SpringBoot多租戶三種架構(gòu)實現(xiàn)方案詳解

下一篇: Git 不要只會 Pull 和 Push,這五條提高效率的命令得掌握!

標(biāo)簽:
  • 熱門焦點
Top