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