摘要:實(shí)現(xiàn)原理淺談幫助理解的示意圖中有一屬性,類(lèi)型是的靜態(tài)內(nèi)部類(lèi)。剛剛說(shuō)過(guò),是一個(gè)中的靜態(tài)內(nèi)部類(lèi),則是的內(nèi)部節(jié)點(diǎn)。這個(gè)會(huì)在線(xiàn)程中,作為其屬性初始是一個(gè)數(shù)組的索引,達(dá)成與類(lèi)似的效果。的方法被調(diào)用時(shí),會(huì)根據(jù)記錄的槽位信息進(jìn)行大掃除。
概述
FastThreadLocal的類(lèi)名本身就充滿(mǎn)了對(duì)ThreadLocal的挑釁,“快男”FastThreadLocal是怎么快的?源碼中類(lèi)注釋坦白如下:
/** * ... * 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,當(dāng)請(qǐng)求頻繁時(shí),這個(gè)小改動(dòng)就會(huì)顯現(xiàn)其效果。
提到FastThreadLocal,就不得不提它的好基友FastThreadLocalThread,簡(jiǎn)單來(lái)說(shuō),F(xiàn)astThreadLocal就是為FastThreadLocalThread量身打造的!
FastThreadLocalThread又是哪個(gè)單位的?且聽(tīng)我慢慢道來(lái)……
FastThreadLocalThread一般來(lái)說(shuō),Netty的client端,是這么創(chuàng)建的:
EventLoopGroup group = new NioEventLoopGroup();
沿著調(diào)用鏈,層層深入NioEventLoopGroup的構(gòu)造函數(shù),在MultithreadEventExecutorGroup的構(gòu)造塊,會(huì)看到這樣的邏輯:
if (executor == null) { executor = new ThreadPerTaskExecutor(newDefaultThreadFactory()); }
newDefaultThreadFactory()方法,功能如其名,創(chuàng)建了DefaultThreadFactory工廠(chǎng):
protected ThreadFactory newDefaultThreadFactory() { return new DefaultThreadFactory(getClass()); }
而DefaultThreadFactory工廠(chǎng)的產(chǎn)品,就是FastThreadLocalThread。
ok,F(xiàn)astThreadLocalThread物種起源的事兒暫且放下,我們來(lái)簡(jiǎn)單過(guò)一下原版ThreadLocal的工作機(jī)制。
ThreadLocalThreadLocal
//賦值方法 public void set(T value); //取值方法 public T get();
用以并發(fā)環(huán)境下,線(xiàn)程生命周期內(nèi)的存取數(shù)據(jù)操作,隔離其它線(xiàn)程干擾。
實(shí)現(xiàn)原理淺談幫助理解的示意圖:
Thread中有一屬性threadLocals,ThreadLocal.ThreadLocalMap類(lèi)型(ThreadLocalMap是ThreadLocal的靜態(tài)內(nèi)部類(lèi))。ThreadLocal的set(T value)方法被調(diào)用時(shí),會(huì)將參數(shù)value存放于當(dāng)前線(xiàn)程的threadLocals中,想要獲取時(shí),再?gòu)?b>threadLocals中獲取。
剛剛說(shuō)過(guò),threadLocals是一個(gè)ThreadLocalMap(ThreadLocal中的靜態(tài)內(nèi)部類(lèi)),Entry則是ThreadLocalMap的內(nèi)部節(jié)點(diǎn)。而ThreadLocalMap作為一個(gè)Map,人設(shè)是這樣的ThreadLocalMap
存入 set(T value)
public void set(T value) { Thread t = Thread.currentThread(); ThreadLocalMap map = getMap(t); //根據(jù)當(dāng)前線(xiàn)程獲取ThreadLocalMap if (map != null) map.set(this, value); //map的key直接使用的當(dāng)前ThreadLocal對(duì)象 else createMap(t, value); }
線(xiàn)程向ThreadLocal存入時(shí),第一次調(diào)用將在線(xiàn)程中分配一塊空間,初始大小為Entry[16]數(shù)組。然后,以作為key的ThreadLocal
獲取 T get()
public T get() { Thread t = Thread.currentThread(); ThreadLocalMap map = getMap(t); //找到與當(dāng)前線(xiàn)程綁定的ThreadLocalMap if (map != null) { ThreadLocalMap.Entry e = map.getEntry(this); if (e != null) { @SuppressWarnings("unchecked") T result = (T)e.value; return result; } } return setInitialValue(); }
獲取時(shí),先找到與當(dāng)前線(xiàn)程綁定的ThreadLocalMap,然后你懂得……
聽(tīng)上去一副滿(mǎn)滿(mǎn)的HashMap的套路,其實(shí)內(nèi)在有很大差別,比如ThreadLocal的Entry實(shí)現(xiàn)了WeakReference(弱引用)。
一個(gè)小問(wèn)題ThreadLocal為什么用Entry數(shù)組作為內(nèi)置實(shí)現(xiàn)?而且初始就16位,還有擴(kuò)容等實(shí)現(xiàn)。對(duì)某一線(xiàn)程而言,ThreadLocal不是只能存儲(chǔ)一個(gè)值嗎?這么想的話(huà),用單個(gè)Object就能存儲(chǔ)了……
這個(gè)萬(wàn)惡的問(wèn)題,當(dāng)時(shí)困擾了我很長(zhǎng)時(shí)間,其實(shí)想通后很簡(jiǎn)單:
Entry數(shù)組為了實(shí)現(xiàn)ThreadLocalMap,而ThreadLocalMap君的key是ThreadLocal,多個(gè)ThreadLocal都可以存儲(chǔ)在ThreadLocalMap中。沒(méi)錯(cuò),A線(xiàn)程只用一個(gè)ThreadLocal的話(huà),確實(shí)用一個(gè)Object作為內(nèi)置實(shí)現(xiàn)就搞定了,但是A線(xiàn)程使用多個(gè)ThreadLocal時(shí),無(wú)法滿(mǎn)足!
ThreadLocal就分析到這里,讓我們回歸FastThreadLocal。
結(jié)構(gòu)及關(guān)鍵方法示意圖:
前文提到過(guò),F(xiàn)astThreadLocal的關(guān)鍵是index,index可以理解成一個(gè)FastThreadLocal對(duì)象的唯一ID。這個(gè)index會(huì)在FastThreadLocalThread線(xiàn)程中,作為其indexedVariables屬性(初始是一個(gè)Object[32]數(shù)組)的索引,達(dá)成與ThreadLocal類(lèi)似的效果。
值得一提的是Object[] indexedVariables的第0位(Object[0]),用于存放未來(lái)會(huì)被釋放的數(shù)據(jù),其實(shí)存儲(chǔ)的就是之前FastThreadLocal的set方法操作過(guò)的槽位信息。FastThreadLocal的remove方法被調(diào)用時(shí),會(huì)根據(jù)記錄的槽位信息進(jìn)行大掃除。
FastThreadLocal相關(guān)內(nèi)容就聊到這里,更多細(xì)節(jié)請(qǐng)翻看源碼!
感謝ThreadLocal源碼解讀
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://m.hztianpu.com/yun/68317.html
摘要:非阻塞模型這種也很好理解,由阻塞的死等系統(tǒng)響應(yīng)進(jìn)化成多次調(diào)用查看數(shù)據(jù)就緒狀態(tài)。復(fù)用模型,以及它的增強(qiáng)版就屬于該種模型。此時(shí)用戶(hù)進(jìn)程阻塞在事件上,數(shù)據(jù)就緒系統(tǒng)予以通知。信號(hào)驅(qū)動(dòng)模型應(yīng)用進(jìn)程建立信號(hào)處理程序時(shí),是非阻塞的。 引言 之前的兩篇文章 FastThreadLocal怎么Fast?、ScheduledThreadPoolExecutor源碼解讀 搞的我心力交瘁,且讀源碼過(guò)程中深感功...
摘要:答曰摸索直譯為服務(wù)加載器,最終目的是獲取的實(shí)現(xiàn)類(lèi)。代碼走起首先,要有一個(gè)接口形狀接口介紹然后,要有該接口的實(shí)現(xiàn)類(lèi)。期具體實(shí)現(xiàn)依靠的內(nèi)部類(lèi),感性趣的朋友可以自己看一下。總結(jié)重點(diǎn)在于可跨越包獲取,這一點(diǎn)筆者通過(guò)多模塊項(xiàng)目親測(cè)延時(shí)加載特性 前戲 netty源碼注釋有云: ... If a provider class has been installed in a jar file tha...
摘要:閱讀源碼時(shí),發(fā)現(xiàn)很多,理所當(dāng)然會(huì)想翻閱資料后,該技能,姿勢(shì)如下環(huán)境中的全部屬性全部屬性注意如果將本行代碼放在自定義屬性之后,會(huì)不會(huì)打出把自定義屬性也給獲取到可以結(jié)論會(huì)獲取目前環(huán)境中全部的屬性值,無(wú)論系統(tǒng)提供還是個(gè)人定義系統(tǒng)提供屬性代碼中定義 閱讀源碼時(shí),發(fā)現(xiàn)很多System.getProperty(xxx),理所當(dāng)然會(huì)想:whats fucking this? 翻閱資料后,Get該技能...
引言 本文是源起netty專(zhuān)欄的第4篇文章,很明顯前3篇文章已經(jīng)在偏離主題的道路上越來(lái)越遠(yuǎn)。于是乎,我決定:繼續(xù)保持…… 使用 首先看看源碼類(lèi)注釋中的示例(未改變官方示例邏輯,只是增加了print輸出和注釋?zhuān)?import java.time.LocalTime; import java.util.concurrent.Executors; import java.util.concurrent....
引言 本文是源起netty專(zhuān)欄的第4篇文章,很明顯前3篇文章已經(jīng)在偏離主題的道路上越來(lái)越遠(yuǎn)。于是乎,我決定:繼續(xù)保持…… 使用 首先看看源碼類(lèi)注釋中的示例(未改變官方示例邏輯,只是增加了print輸出和注釋?zhuān)?import java.time.LocalTime; import java.util.concurrent.Executors; import java.util.concurrent....
閱讀 1893·2021-10-09 09:44
閱讀 2762·2021-09-22 15:38
閱讀 2581·2021-09-09 09:33
閱讀 778·2021-09-07 09:58
閱讀 1895·2021-09-02 15:41
閱讀 2647·2019-08-30 15:55
閱讀 1865·2019-08-30 15:55
閱讀 632·2019-08-30 15:44