成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

【源起Netty 外傳】FastThreadLocal怎么Fast?

gxyz / 418人閱讀

摘要:實現(xiàn)原理淺談幫助理解的示意圖中有一屬性,類型是的靜態(tài)內(nèi)部類。剛剛說過,是一個中的靜態(tài)內(nèi)部類,則是的內(nèi)部節(jié)點。這個會在線程中,作為其屬性初始是一個數(shù)組的索引,達成與類似的效果。的方法被調(diào)用時,會根據(jù)記錄的槽位信息進行大掃除。

概述

FastThreadLocal的類名本身就充滿了對ThreadLocal的挑釁,“快男”FastThreadLocal是怎么快的?源碼中類注釋坦白如下:

/**
 * ...
 * Internally, a {@link FastThreadLocal} uses a constant index in an array, instead of using hash code and hash table,
 * to look for a variable.  Although seemingly very subtle, it yields slight performance advantage over using a hash
 * table, and it is useful when accessed frequently.
 * ...
 */

大概意思就是:用索引代替了ThreadLocal中的threadLocalHashCode,當請求頻繁時,這個小改動就會顯現(xiàn)其效果。
提到FastThreadLocal,就不得不提它的好基友FastThreadLocalThread,簡單來說,F(xiàn)astThreadLocal就是為FastThreadLocalThread量身打造的!

FastThreadLocalThread又是哪個單位的?且聽我慢慢道來……

FastThreadLocalThread

一般來說,Netty的client端,是這么創(chuàng)建的:

EventLoopGroup group = new NioEventLoopGroup();

沿著調(diào)用鏈,層層深入NioEventLoopGroup的構(gòu)造函數(shù),在MultithreadEventExecutorGroup構(gòu)造塊,會看到這樣的邏輯:

if (executor == null) {
    executor = new ThreadPerTaskExecutor(newDefaultThreadFactory());
}

newDefaultThreadFactory()方法,功能如其名,創(chuàng)建了DefaultThreadFactory工廠:

protected ThreadFactory newDefaultThreadFactory() {
    return new DefaultThreadFactory(getClass());
}

DefaultThreadFactory工廠的產(chǎn)品,就是FastThreadLocalThread。

ok,F(xiàn)astThreadLocalThread物種起源的事兒暫且放下,我們來簡單過一下原版ThreadLocal的工作機制。

ThreadLocal

ThreadLocal大家應該并不陌生,兩個最核心API

//賦值方法
public void set(T value);

//取值方法
public T get();

用以并發(fā)環(huán)境下,線程生命周期內(nèi)的存取數(shù)據(jù)操作,隔離其它線程干擾。

實現(xiàn)原理淺談

幫助理解的示意圖:

Thread中有一屬性threadLocals,ThreadLocal.ThreadLocalMap類型(ThreadLocalMap是ThreadLocal的靜態(tài)內(nèi)部類)。ThreadLocal的set(T value)方法被調(diào)用時,會將參數(shù)value存放于當前線程的threadLocals中,想要獲取時,再從threadLocals中獲取。

剛剛說過,threadLocals是一個ThreadLocalMap(ThreadLocal中的靜態(tài)內(nèi)部類),Entry則是ThreadLocalMap的內(nèi)部節(jié)點。而ThreadLocalMap作為一個Map,人設是這樣的ThreadLocalMap>,T>,即key=ThreadLocalvalue=T。

存入 set(T value)

public void set(T value) {
    Thread t = Thread.currentThread();
    ThreadLocalMap map = getMap(t);    //根據(jù)當前線程獲取ThreadLocalMap
    if (map != null)
        map.set(this, value);    //map的key直接使用的當前ThreadLocal對象
    else
        createMap(t, value);
}  

線程向ThreadLocal存入時,第一次調(diào)用將在線程中分配一塊空間,初始大小為Entry[16]數(shù)組。然后,以作為key的ThreadLocal計算出hashCode,稍加計算得出Entry[16]數(shù)組的索引i。最后,為槽位Entry[i]賦值上value。

獲取 T get()

public T get() {
    Thread t = Thread.currentThread();
    ThreadLocalMap map = getMap(t);    //找到與當前線程綁定的ThreadLocalMap
    if (map != null) {
        ThreadLocalMap.Entry e = map.getEntry(this);
        if (e != null) {
            @SuppressWarnings("unchecked")
            T result = (T)e.value;
            return result;
        }
    }
    return setInitialValue();
}

獲取時,先找到與當前線程綁定的ThreadLocalMap,然后你懂得……

聽上去一副滿滿的HashMap的套路,其實內(nèi)在有很大差別,比如ThreadLocal的Entry實現(xiàn)了WeakReference弱引用)。

一個小問題

ThreadLocal為什么用Entry數(shù)組作為內(nèi)置實現(xiàn)?而且初始就16位,還有擴容等實現(xiàn)。對某一線程而言,ThreadLocal不是只能存儲一個值嗎?這么想的話,用單個Object就能存儲了……

這個萬惡的問題,當時困擾了我很長時間,其實想通后很簡單:
Entry數(shù)組為了實現(xiàn)ThreadLocalMap,而ThreadLocalMap君的key是ThreadLocal,多個ThreadLocal都可以存儲在ThreadLocalMap中。沒錯,A線程只用一個ThreadLocal的話,確實用一個Object作為內(nèi)置實現(xiàn)就搞定了,但是A線程使用多個ThreadLocal時,無法滿足!

FastThreadLocal

ThreadLocal就分析到這里,讓我們回歸FastThreadLocal。

結(jié)構(gòu)及關鍵方法示意圖:

前文提到過,F(xiàn)astThreadLocal的關鍵是index,index可以理解成一個FastThreadLocal對象的唯一ID。這個index會在FastThreadLocalThread線程中,作為其indexedVariables屬性(初始是一個Object[32]數(shù)組)的索引,達成與ThreadLocal類似的效果。

值得一提的是Object[] indexedVariables的第0位(Object[0]),用于存放未來會被釋放的數(shù)據(jù),其實存儲的就是之前FastThreadLocal的set方法操作過的槽位信息。FastThreadLocal的remove方法被調(diào)用時,會根據(jù)記錄的槽位信息進行大掃除。

FastThreadLocal相關內(nèi)容就聊到這里,更多細節(jié)請翻看源碼!

感謝

ThreadLocal源碼解讀

文章版權歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/68317.html

相關文章

  • 源起Netty 前傳】Linux網(wǎng)絡模型小記

    摘要:非阻塞模型這種也很好理解,由阻塞的死等系統(tǒng)響應進化成多次調(diào)用查看數(shù)據(jù)就緒狀態(tài)。復用模型,以及它的增強版就屬于該種模型。此時用戶進程阻塞在事件上,數(shù)據(jù)就緒系統(tǒng)予以通知。信號驅(qū)動模型應用進程建立信號處理程序時,是非阻塞的。 引言 之前的兩篇文章 FastThreadLocal怎么Fast?、ScheduledThreadPoolExecutor源碼解讀 搞的我心力交瘁,且讀源碼過程中深感功...

    Null 評論0 收藏0
  • 源起Netty 外傳】ServiceLoader詳解

    摘要:答曰摸索直譯為服務加載器,最終目的是獲取的實現(xiàn)類。代碼走起首先,要有一個接口形狀接口介紹然后,要有該接口的實現(xiàn)類。期具體實現(xiàn)依靠的內(nèi)部類,感性趣的朋友可以自己看一下??偨Y(jié)重點在于可跨越包獲取,這一點筆者通過多模塊項目親測延時加載特性 前戲 netty源碼注釋有云: ... If a provider class has been installed in a jar file tha...

    MoAir 評論0 收藏0
  • 源起Netty 外傳】System.getPropert()詳解

    摘要:閱讀源碼時,發(fā)現(xiàn)很多,理所當然會想翻閱資料后,該技能,姿勢如下環(huán)境中的全部屬性全部屬性注意如果將本行代碼放在自定義屬性之后,會不會打出把自定義屬性也給獲取到可以結(jié)論會獲取目前環(huán)境中全部的屬性值,無論系統(tǒng)提供還是個人定義系統(tǒng)提供屬性代碼中定義 閱讀源碼時,發(fā)現(xiàn)很多System.getProperty(xxx),理所當然會想:whats fucking this? 翻閱資料后,Get該技能...

    lixiang 評論0 收藏0
  • 源起Netty 外傳】ScheduledThreadPoolExecutor源碼解讀

    引言 本文是源起netty專欄的第4篇文章,很明顯前3篇文章已經(jīng)在偏離主題的道路上越來越遠。于是乎,我決定:繼續(xù)保持…… 使用 首先看看源碼類注釋中的示例(未改變官方示例邏輯,只是增加了print輸出和注釋) import java.time.LocalTime; import java.util.concurrent.Executors; import java.util.concurrent....

    funnyZhang 評論0 收藏0
  • 源起Netty 外傳】ScheduledThreadPoolExecutor源碼解讀

    引言 本文是源起netty專欄的第4篇文章,很明顯前3篇文章已經(jīng)在偏離主題的道路上越來越遠。于是乎,我決定:繼續(xù)保持…… 使用 首先看看源碼類注釋中的示例(未改變官方示例邏輯,只是增加了print輸出和注釋) import java.time.LocalTime; import java.util.concurrent.Executors; import java.util.concurrent....

    Eastboat 評論0 收藏0

發(fā)表評論

0條評論

最新活動
閱讀需要支付1元查看
<