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

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

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

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

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

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

1.先從ThreadLocal說(shuō)起

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

ThreadLocal 底層是使用 ThreadLocalMap 實(shí)現(xiàn)的,這點(diǎn)從 JDK 的源碼中可以看出,核心源碼如下:pZp28資訊網(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 是存儲(chǔ)在 ThreadLocalMap 中的,咱們繼續(xù)看 ThreadLocalMap 的源碼實(shí)現(xiàn):pZp28資訊網(wǎng)——每日最新資訊28at.com

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

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

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

2.ThreadLocal存在的問(wèn)題

(1)性能問(wèn)題

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

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

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

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

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

3.FastThreadLocal特點(diǎn)

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

(1)效率高

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

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

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

public final class InternalThreadLocalMap extends UnpaddedInternalThreadLocalMap {    // 自增索引, ?于計(jì)算下次存儲(chǔ)到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í)候分配一個(gè)數(shù)組索引 index,index 的值采用原子類 AtomicInteger 保證順序遞增,通過(guò)調(diào)用 InternalThreadLocalMap.nextVariableIndex() 方法獲得。然后在讀寫數(shù)據(jù)的時(shí)候通過(guò)數(shù)組下標(biāo) index 直接定位到 FastThreadLocal 的位置,時(shí)間復(fù)雜度為 O(1)。如果數(shù)組下標(biāo)遞增到非常大,那么數(shù)組也會(huì)比較大,所以 FastThreadLocal 是通過(guò)空間換時(shí)間的思想提升讀寫性能。pZp28資訊網(wǎng)——每日最新資訊28at.com

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

(2)安全性更高

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

FastThreadLocalRunnable 自動(dòng)清除對(duì)象的實(shí)現(xiàn)核心源碼如下:pZp28資訊網(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 存在以下兩個(gè)主要優(yōu)點(diǎn):pZp28資訊網(wǎng)——每日最新資訊28at.com

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

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

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

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

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

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