Netty分布式高性能工具類recycler的使用及創(chuàng)建
前文傳送門:Netty分布式FastThreadLocal的set方法實(shí)現(xiàn)邏輯剖析
recycler的使用
這一小節(jié)開(kāi)始學(xué)習(xí)recycler相關(guān)的知識(shí), recycler是netty實(shí)現(xiàn)的一個(gè)輕量級(jí)對(duì)象回收站, 在netty中, recycler的使用也是相當(dāng)之頻繁的
recycler作用是保證了對(duì)象的循環(huán)利用, 對(duì)象使用完可以通過(guò)recycler回收, 需要再次使用則從對(duì)象池中取出, 不用每次都創(chuàng)建新對(duì)象從而減少對(duì)系統(tǒng)資源的占用, 同時(shí)也減輕了gc的壓力
這里看一個(gè)示例
public class RecyclerDemo { private static final Recycler<User> RECYCLER = new Recycler<User>() { @Override protected User newObject(Handle<User> handle) { return new User(handle); } }; static class User{ private final Recycler.Handle<User> handle; public User(Recycler.Handle<User> handle){ this.handle=handle; } public void recycle(){ handle.recycle(this); } } public static void main(String[] args){ User user1 = RECYCLER.get(); user1.recycle(); User user2 = RECYCLER.get(); user2.recycle(); System.out.println(user1==user2); } }
首先定義了一個(gè)Recycler的成員變量RECYCLER, 在匿名內(nèi)部類中重寫了newObject方法, 也就是創(chuàng)建對(duì)象的方法, 該方法就是用戶自定義的
這里newObject返回的new User(handle), 代表當(dāng)回收站沒(méi)有此類對(duì)象的時(shí)候, 可以通過(guò)這種方式創(chuàng)建對(duì)象
成員變量RECYCLER, 可以用來(lái)對(duì)此類對(duì)象的回收和再利用
定一個(gè)了一個(gè)靜態(tài)內(nèi)部類User, User中有個(gè)成員變量handle, 在構(gòu)造方法中為其賦值, handle的作用, 就是用于對(duì)象回收的
并且定義了一個(gè)方法recycle, 方法體中通過(guò)handle.recycle(this)這種方式將自身對(duì)象進(jìn)行回收, 通過(guò)這步操作, 就可以將對(duì)象回收到Recycler中
以上邏輯先做了解, 之后會(huì)進(jìn)行詳細(xì)分析
在main方法中, 通過(guò)RECYCLER的get方法獲取一個(gè)user, 然后進(jìn)行回收
再通過(guò)get方法將回收站的對(duì)象取出, 再次進(jìn)行回收, 最后判斷兩次取出的對(duì)象是否為一個(gè)對(duì)象, 最后結(jié)果輸出為true
以上demo就可以說(shuō)明Recycler的回收再利用的功能
簡(jiǎn)單介紹了demo, 我們就詳細(xì)的分析Recycler的機(jī)制
在Recycler的類的源碼中, 我們看到這一段邏輯
private final FastThreadLocal<Stack<T>> threadLocal = new FastThreadLocal<Stack<T>>() { @Override protected Stack<T> initialValue() { return new Stack<T>(Recycler.this, Thread.currentThread(), maxCapacityPerThread, maxSharedCapacityFactor, ratioMask, maxDelayedQueuesPerThread); } };
這一段邏輯我們并不陌生, 在上一小節(jié)的學(xué)習(xí)中我們知道, 這里用于保存線程共享對(duì)象, 而這里的共享對(duì)象, 就是一個(gè)Stack類型的對(duì)象
每個(gè)stack中維護(hù)著一個(gè)DefaultHandle類型的數(shù)組, 用于盛放回收的對(duì)象, 有關(guān)stack和線程的關(guān)系如圖所示:
8-3-1
也就是說(shuō)在每個(gè)Recycler中, 都維護(hù)著一個(gè)線程共享的棧, 用于對(duì)一類對(duì)象的回收
跟到Stack的構(gòu)造方法中
Stack(Recycler<T> parent, Thread thread, int maxCapacity, int maxSharedCapacityFactor, int ratioMask, int maxDelayedQueues) { this.parent = parent; this.thread = thread; this.maxCapacity = maxCapacity; availableSharedCapacity = new AtomicInteger(max(maxCapacity / maxSharedCapacityFactor, LINK_CAPACITY)); elements = new DefaultHandle[min(INITIAL_CAPACITY, maxCapacity)]; this.ratioMask = ratioMask; this.maxDelayedQueues = maxDelayedQueues; }
首先介紹幾個(gè)構(gòu)造方法中初始化的關(guān)鍵屬性:
屬性parent表示Reclycer對(duì)象自身
屬性thread表示當(dāng)前stack綁定的哪個(gè)線程
屬性maxCapacity表示當(dāng)前stack的最大容量, 表示stack最多能盛放多少個(gè)元素
屬性elements, 就表示stack中存儲(chǔ)的對(duì)象, 類型為DefaultHandle, 可以被外部對(duì)象引用, 從而實(shí)現(xiàn)回收
屬性ratioMask是用來(lái)控制對(duì)象回收的頻率的, 也就是說(shuō)每次通過(guò)Reclycer回收對(duì)象的時(shí)候, 不是每次都會(huì)進(jìn)行回收, 而是通過(guò)該參數(shù)控制回收頻率
屬性maxDelayedQueues, 這里稍微有些復(fù)雜, 在很多時(shí)候, 一個(gè)線程創(chuàng)建的對(duì)象, 有可能會(huì)被另一個(gè)線程所釋放, 而另一個(gè)線程釋放的對(duì)象是不會(huì)放在當(dāng)前線程的stack中的, 而是會(huì)存放在一個(gè)叫做WeakOrderQueue的數(shù)據(jù)結(jié)構(gòu)中, 里面也是存放著一個(gè)個(gè)DefaultHandle, WeakOrderQueue會(huì)存放線程1創(chuàng)建的并且在線程2進(jìn)行釋放的對(duì)象
這里只是稍作了解, 之后的會(huì)對(duì)此做詳細(xì)剖析, 這里我們只需知道, maxDelayedQueues屬性的意思就是我這個(gè)線程能回收幾個(gè)其他創(chuàng)建的對(duì)象的線程, 假設(shè)當(dāng)前線程是線程1, maxDelayedQueues為2, 那么我線程1回收了線程2創(chuàng)建的對(duì)象, 又回收了線程3創(chuàng)建的對(duì)象, 那么不可能回收線程4創(chuàng)建的對(duì)象了, 因?yàn)閙axDelayedQueues2, 我只能回收兩個(gè)線程創(chuàng)建的對(duì)象
屬性availableSharedCapacity, 表示在線程1中創(chuàng)建的對(duì)象, 在其他線程中緩存的最大個(gè)數(shù), 同樣, 相關(guān)邏輯會(huì)在之后的內(nèi)容進(jìn)行剖析
另外介紹兩個(gè)沒(méi)有在構(gòu)造方法初始化的屬性:
private WeakOrderQueue cursor, prev; private volatile WeakOrderQueue head;
這里相當(dāng)于指針, 用于指向WeakOrderQueue的, 這里也是稍作了解, 之后會(huì)進(jìn)行詳細(xì)剖析
有關(guān)stack異線程之間對(duì)象的關(guān)系如圖所示(簡(jiǎn)略):
8-3-2
我們?cè)倮^續(xù)介紹Recycler的構(gòu)造方法, 同時(shí)熟悉有關(guān)stack各個(gè)參數(shù)的默認(rèn)值:
protected Recycler() { this(DEFAULT_MAX_CAPACITY_PER_THREAD); }
這里調(diào)用了重載的構(gòu)造方法, 并傳入了參數(shù)DEFAULT_MAX_CAPACITY_PER_THREAD
DEFAULT_MAX_CAPACITY_PER_THREAD的默認(rèn)值是32768, 在static塊中被初始化的, 我們可以跟進(jìn)去自行分析
這個(gè)值就代表的每個(gè)線程中, stack中最多回收的元素的個(gè)數(shù)
繼續(xù)跟重載的構(gòu)造方法
protected Recycler(int maxCapacityPerThread) { this(maxCapacityPerThread, MAX_SHARED_CAPACITY_FACTOR); }
這里又調(diào)用了重載的構(gòu)造方法, 并且傳入剛才傳入的32768和MAX_SHARED_CAPACITY_FACTOR
MAX_SHARED_CAPACITY_FACTOR默認(rèn)值是2, 同樣在static塊中進(jìn)行了初始化, 有關(guān)該屬性的用處稍后講解
繼續(xù)跟構(gòu)造方法:
protected Recycler(int maxCapacityPerThread, int maxSharedCapacityFactor) { this(maxCapacityPerThread, maxSharedCapacityFactor, RATIO, MAX_DELAYED_QUEUES_PER_THREAD); }
這里同樣調(diào)用了重載的構(gòu)造方法, 傳入了剛才32768和2, 還有兩個(gè)屬性RATIO和MAX_DELAYED_QUEUES_PER_THREAD
RATIO也在static中被初始化, 默認(rèn)值是8
同上, MAX_DELAYED_QUEUES_PER_THREAD的默認(rèn)值是2倍cpu核數(shù)
我們繼續(xù)跟構(gòu)造方法:
protected Recycler(int maxCapacityPerThread, int maxSharedCapacityFactor, int ratio, int maxDelayedQueuesPerThread) { ratioMask = safeFindNextPositivePowerOfTwo(ratio) - 1; if (maxCapacityPerThread <= 0) { this.maxCapacityPerThread = 0; this.maxSharedCapacityFactor = 1; this.maxDelayedQueuesPerThread = 0; } else { this.maxCapacityPerThread = maxCapacityPerThread; this.maxSharedCapacityFactor = max(1, maxSharedCapacityFactor); this.maxDelayedQueuesPerThread = max(0, maxDelayedQueuesPerThread); } }
這里將幾個(gè)屬性進(jìn)行了初始化
首先看ratioMask, 這里的方法safeFindNextPositivePowerOfTwo的參數(shù)ratio為8, 該方法的意思就是大于等于8的2的冪次方-1, 這里就是ratioMask就是7
maxCapacityPerThread是剛才分析的32768, 是一個(gè)大于0的數(shù), 所以進(jìn)入else
maxCapacityPerThread為32768
maxSharedCapacityFactor的值為2
maxDelayedQueuesPerThread的值為2倍CPU核數(shù)
我們?cè)倩氐絊tack的構(gòu)造方法中
Stack(Recycler<T> parent, Thread thread, int maxCapacity, int maxSharedCapacityFactor, int ratioMask, int maxDelayedQueues) { this.parent = parent; this.thread = thread; this.maxCapacity = maxCapacity; availableSharedCapacity = new AtomicInteger(max(maxCapacity / maxSharedCapacityFactor, LINK_CAPACITY)); elements = new DefaultHandle[min(INITIAL_CAPACITY, maxCapacity)]; this.ratioMask = ratioMask; this.maxDelayedQueues = maxDelayedQueues; }
根據(jù)Recycler初始化屬性的邏輯, 我們可以知道Stack中幾個(gè)屬性的值:
maxCapacity默認(rèn)值為32768
ratioMask默認(rèn)值為7
maxDelayedQueues默認(rèn)值是兩倍cpu核數(shù)
availableSharedCapacity的默認(rèn)值是32768/2, 也就是16384
以上就是Recycler創(chuàng)建的相關(guān)邏輯,更多關(guān)于Netty分布式工具類recycler使用的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
SpringCloud中的Eureka注冊(cè)中心詳細(xì)解讀
這篇文章主要介紹了SpringCloud中的Eureka注冊(cè)中心詳細(xì)解讀,想要參與服務(wù)注冊(cè)發(fā)現(xiàn)的實(shí)例首先需要向Eureka服務(wù)器注冊(cè)信息,注冊(cè)在第一次心跳發(fā)生時(shí)提交,需要的朋友可以參考下2023-11-11elasticsearch索引index之Mapping實(shí)現(xiàn)關(guān)系結(jié)構(gòu)示例
這篇文章主要介紹了elasticsearch索引index之Mapping實(shí)現(xiàn)關(guān)系結(jié)構(gòu)示例,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-04-04Spring3 整合MyBatis3 配置多數(shù)據(jù)源動(dòng)態(tài)選擇SqlSessionFactory詳細(xì)教程
這篇文章主要介紹了Spring3 整合MyBatis3 配置多數(shù)據(jù)源動(dòng)態(tài)選擇SqlSessionFactory詳細(xì)教程,需要的朋友可以參考下2017-04-04快速解決idea打開(kāi)某個(gè)項(xiàng)目卡住的問(wèn)題
這篇文章主要介紹了解決idea打開(kāi)某個(gè)項(xiàng)目卡住的問(wèn)題,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-08-08Java8(291)之后禁用了TLS1.1使JDBC無(wú)法用SSL連接SqlServer2008的解決方法
這篇文章主要介紹了Java8(291)之后禁用了TLS1.1使JDBC無(wú)法用SSL連接SqlServer2008的解決方法,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2023-03-03maven插件spring-boot-starter-tomcat的使用方式
這篇文章主要介紹了maven插件spring-boot-starter-tomcat的使用方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-07-07SpringBoot中@Scheduled()注解以及cron表達(dá)式詳解
這篇文章主要介紹了SpringBoot中@Scheduled()注解以及cron表達(dá)式詳解,@Scheduled注解是Spring Boot提供的用于定時(shí)任務(wù)控制的注解,主要用于控制任務(wù)在某個(gè)指定時(shí)間執(zhí)行,或者每隔一段時(shí)間執(zhí)行,需要的朋友可以參考下2023-08-08多線程Thread,Runnable,Callable實(shí)現(xiàn)方式
這篇文章主要為大家詳細(xì)介紹了Java多線程如何實(shí)現(xiàn)Thread,Runnable,Callable的方式,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-08-08springboot(thymeleaf)中th:field和th:value的區(qū)別及說(shuō)明
這篇文章主要介紹了springboot(thymeleaf)中th:field和th:value的區(qū)別及說(shuō)明,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-10-10