Netty分布式高性能工具類同線程下回收對(duì)象解析
同線程回收對(duì)象
上一小節(jié)剖析了從recycler中獲取一個(gè)對(duì)象, 這一小節(jié)分析在創(chuàng)建和回收是同線程的前提下, recycler是如何進(jìn)行回收的
回顧第三小節(jié)的demo中的main方法
public static void main(String[] args){
User user1 = RECYCLER.get();
user1.recycle();
User user2 = RECYCLER.get();
user2.recycle();
System.out.println(user1==user2);
}這里就是一個(gè)同線程回收對(duì)象的典型場(chǎng)景, 在一個(gè)線程中將對(duì)象創(chuàng)建并且回收, 我們的User對(duì)象定義了recycle方法
static class User{
private final Recycler.Handle<User> handle;
public User(Recycler.Handle<User> handle){
this.handle=handle;
}
public void recycle(){
handle.recycle(this);
}
}這里的recycle是通過handle對(duì)象的recycle方法實(shí)現(xiàn)對(duì)象回收的, 這里實(shí)際調(diào)用的是DefaultHandle的recycle方法
我們跟進(jìn)recycle方法
public void recycle(Object object) {
if (object != value) {
throw new IllegalArgumentException("object does not belong to handle");
}
stack.push(this);
}這里如果回收的對(duì)象為null, 則拋出異常
如果不為null, 則通過自身綁定stack的push方法將自身push到stack中
跟到push方法中:
void push(DefaultHandle<?> item) {
Thread currentThread = Thread.currentThread();
if (thread == currentThread) {
pushNow(item);
} else {
pushLater(item, currentThread);
}
}這里首先判斷當(dāng)前線程, 和創(chuàng)建stack的時(shí)候保存的線程是否是同一線程, 如果是, 說明是同線程回收對(duì)象, 則執(zhí)行pushNow方法將對(duì)象放入stack中
跟到pushNow方法中:
private void pushNow(DefaultHandle<?> item) {
if ((item.recycleId | item.lastRecycledId) != 0) {
throw new IllegalStateException("recycled already");
}
item.recycleId = item.lastRecycledId = OWN_THREAD_ID;
int size = this.size;
if (size >= maxCapacity || dropHandle(item)) {
return;
}
if (size == elements.length) {
elements = Arrays.copyOf(elements, min(size << 1, maxCapacity));
}
elements[size] = item;
this.size = size + 1;
}如果第一次回收, item.recycleId和item.lastRecycledId都為0, 所以不會(huì)進(jìn)入if塊, 我們繼續(xù)往下看
item.recycleId = item.lastRecycledId = OWN_THREAD_ID 這一步將handle的recycleId和lastRecycledId賦值為OWN_THREAD_ID, OWN_THREAD_ID在每一個(gè)recycle中是唯一固定的, 這里我們只需要記得這個(gè)概念就行
然后獲取當(dāng)前size
如果size超過上限大小, 則直接返回
這里還有個(gè)判斷dropHandle, 我們跟進(jìn)去:
boolean dropHandle(DefaultHandle<?> handle) {
if (!handle.hasBeenRecycled) {
if ((++handleRecycleCount & ratioMask) != 0) {
return true;
}
handle.hasBeenRecycled = true;
}
return false;
}if (!handle.hasBeenRecycled) 表示當(dāng)前對(duì)象之前是否沒有被回收過, 如果是第一次回收, 這里會(huì)返回true, 然后進(jìn)入放到if
再看if中的判斷
if ((++handleRecycleCount & ratioMask) != 0)
handleRecycleCount表示當(dāng)前位置stack回收了多少次對(duì)象(回收了多少次, 不代表回收了多少個(gè)對(duì)象, 因?yàn)椴皇敲看位厥斩紩?huì)被成功的保存在stack), ratioMask我們之前分析過是7, 這里 (++handleRecycleCount & ratioMask) != 0 表示回收的對(duì)象數(shù)如果不是8的倍數(shù), 則返回true, 表示只回收1/8的對(duì)象
然后將hasBeenRecycled設(shè)置為true, 表示已經(jīng)被回收
回到pushNow方法中:
如果size的大小等于stack中的數(shù)組elements的大小, 則將數(shù)組elements進(jìn)行擴(kuò)容
最后將size通過數(shù)組下標(biāo)的方式將當(dāng)前handle設(shè)置到elements的元素中, 并將size進(jìn)行自增
以上就是同線程回收對(duì)象的邏輯,更多關(guān)于Netty分布式同線程回收對(duì)象的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
java網(wǎng)絡(luò)編程之socket網(wǎng)絡(luò)編程示例(服務(wù)器端/客戶端)
這篇文章主要介紹了java socket網(wǎng)絡(luò)編程的示例,分為服務(wù)器端和客戶端,大家參考使用吧2014-01-01
Java從內(nèi)存角度帶你理解數(shù)組名實(shí)質(zhì)是個(gè)地址的論述
這篇文章主要介紹了Java如何從內(nèi)存解析的角度理解“數(shù)組名實(shí)質(zhì)是一個(gè)地址”,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)吧2022-09-09
nacos使用占位符${}進(jìn)行參數(shù)配置的方法
這篇文章主要介紹了nacos如何使用占位符${}進(jìn)行參數(shù)配置,本文結(jié)合示例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2022-12-12
Spring五大類注解讀取存儲(chǔ)Bean對(duì)象的方法
這篇文章主要介紹了Spring五大類注解讀取存儲(chǔ)Bean對(duì)象,本文通過示例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2022-09-09
Java基礎(chǔ)之Comparable與Comparator概述
這篇文章主要介紹了Java基礎(chǔ)之Comparable與Comparator詳解,文中有非常詳細(xì)的代碼示例,對(duì)正在學(xué)習(xí)java基礎(chǔ)的小伙伴們有非常好的幫助,需要的朋友可以參考下2021-04-04
SpringBoot使用maven指定依賴包的版本(解決示例)
我們?cè)谑褂肁依賴的時(shí)候,這個(gè)依賴有引入了第三方B依賴,這時(shí)候我想指定B依賴的版本號(hào),下面?zhèn)€大家分享解決示例,對(duì)SpringBoot maven依賴包相關(guān)配置方法感興趣的朋友一起看看吧2024-04-04
java thread start()和run()方法簡(jiǎn)析
本文以java中thread的start()和run()的區(qū)別做詳細(xì)介紹, 需要了解跟多的朋友可以參考下2012-11-11
如何用注解的方式實(shí)現(xiàn)Mybatis插入數(shù)據(jù)時(shí)返回自增的主鍵Id
這篇文章主要介紹了如何用注解的方式實(shí)現(xiàn)Mybatis插入數(shù)據(jù)時(shí)返回自增的主鍵Id,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-07-07
SpringBoot調(diào)用第三方接口的幾種方式小結(jié)
在項(xiàng)目中調(diào)用第三方接口時(shí),確實(shí)需要根據(jù)項(xiàng)目的技術(shù)棧、架構(gòu)規(guī)范以及具體的業(yè)務(wù)需求來選擇最適合的調(diào)用方式,下面我們就介紹幾種調(diào)用第三方接口的實(shí)現(xiàn)方式以及代碼示例,需要的朋友可以參考下2024-07-07

