Netty分布式從recycler對(duì)象回收站獲取對(duì)象過程剖析
前文傳送門:Netty分布式高性能工具類recycler的使用及創(chuàng)建
從對(duì)象回收站中獲取對(duì)象
我們回顧上一小節(jié)demo的main方法中
從回收站獲取對(duì)象
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的get方法獲取對(duì)象, 我們跟到get方法中:
public final T get() {
if (maxCapacityPerThread == 0) {
return newObject((Handle<T>) NOOP_HANDLE);
}
Stack<T> stack = threadLocal.get();
DefaultHandle<T> handle = stack.pop();
if (handle == null) {
handle = stack.newHandle();
handle.value = newObject(handle);
}
return (T) handle.value;
}首先判斷maxCapacityPerThread是否為0, maxCapacityPerThread代表stack最多能緩存多少個(gè)對(duì)象, 如果緩存0個(gè), 說明對(duì)象將一個(gè)都不會(huì)回收
這個(gè)通過調(diào)用newObject創(chuàng)建一個(gè)對(duì)象, 并傳入一個(gè)NOOP_HANDLE, NOOP_HANDLE是一個(gè)handle, 我們看其定義:
private static final Handle NOOP_HANDLE = new Handle() {
@Override
public void recycle(Object object) {
}
};這里的recycle方法是一個(gè)空實(shí)現(xiàn), 代表不進(jìn)行任何對(duì)象回收
回到get方法中
我們看第二步
Stack<T> stack = threadLocal.get();
這里通過FastThreadLocal對(duì)象拿到當(dāng)前線程的stack, 有關(guān)FastThreadLocal獲取對(duì)象的邏輯之前小節(jié)剖析過, 這里不再贅述
獲取stack之后, 從stack中pop出一個(gè)handle, 這個(gè)handle做用我們稍后分析
如果取出的對(duì)象為null, 說明當(dāng)前回收站內(nèi)沒有任何對(duì)象, 通常第一次執(zhí)行到這里對(duì)象還沒回收, 這里就會(huì)是null, 這樣則會(huì)通過stack.newHandle()創(chuàng)建一個(gè)handle
創(chuàng)建出來的handle的value屬性, 通過我們重寫的newObject方法進(jìn)行賦值, 也就是我們demo中的user
我們跟進(jìn)newHandle方法
DefaultHandle<T> newHandle() {
return new DefaultHandle<T>(this);
}這里創(chuàng)建一個(gè)DefaultHandle對(duì)象, 并傳入this, 這里的this是當(dāng)前stack
跟到DefaultHandle的構(gòu)造方法中:
DefaultHandle(Stack<?> stack) {
this.stack = stack;
}這里初始化了stack屬性
DefaultHandle中還有個(gè)value的成員變量
private Object value;
這里的value就用來綁定回收的對(duì)象本身
回到get方法中:
分析handle, 我們回到上一步:
DefaultHandle<T> handle = stack.pop();
我們分析從stack中彈出一個(gè)handle的邏輯
跟到pop方法中
DefaultHandle<T> pop() {
int size = this.size;
if (size == 0) {
if (!scavenge()) {
return null;
}
size = this.size;
}
size --;
DefaultHandle ret = elements[size];
elements[size] = null;
if (ret.lastRecycledId != ret.recycleId) {
throw new IllegalStateException("recycled multiple times");
}
ret.recycleId = 0;
ret.lastRecycledId = 0;
this.size = size;
return ret;
}首先拿到size, size表示當(dāng)前stack的對(duì)象數(shù)
如果size為0, 則調(diào)用scavenge方法, 這個(gè)方法是異線程回收對(duì)象的方法, 我們放在之后的小節(jié)進(jìn)行分析
size大于零, 則size進(jìn)行自減, 代表取出一個(gè)元素
然后通過size的數(shù)組下標(biāo)的方式將handle取出
之后將當(dāng)前下標(biāo)設(shè)置為null
最后將屬性recycleId, lastRecycledId, size進(jìn)行賦值
recycleId和lastRecycledId我們會(huì)在之后的小節(jié)進(jìn)行分析
回到get方法中:
public final T get() {
if (maxCapacityPerThread == 0) {
return newObject((Handle<T>) NOOP_HANDLE);
}
Stack<T> stack = threadLocal.get();
DefaultHandle<T> handle = stack.pop();
if (handle == null) {
handle = stack.newHandle();
handle.value = newObject(handle);
}
return (T) handle.value;
}無論是從stack中彈出的handle, 還是創(chuàng)建的handle, 最后都要通過handle.value拿到我們實(shí)際使用的對(duì)象
以上就是從對(duì)象回收站獲取對(duì)象的過程,更多關(guān)于Netty分布式recycler獲取對(duì)象的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
詳解Java動(dòng)態(tài)字節(jié)碼技術(shù)
Java字節(jié)碼增強(qiáng)指的是在Java字節(jié)碼生成之后,對(duì)其進(jìn)行修改,增強(qiáng)其功能,可減少冗余代碼,提高性能等。本文將詳細(xì)介紹Java動(dòng)態(tài)字節(jié)碼技術(shù)。2021-05-05
SpringBoot使用Nacos進(jìn)行application.yml配置管理
Nacos是阿里巴巴開源的一個(gè)微服務(wù)配置管理和服務(wù)發(fā)現(xiàn)的解決方案,它提供了動(dòng)態(tài)服務(wù)發(fā)現(xiàn)、配置管理和?服務(wù)管理平臺(tái),Nacos使用Raft協(xié)議保證配置的一致性,同時(shí)支持多種配置?格式,如properties、yaml等,本文介紹了SpringBoot使用Nacos進(jìn)行application.yml配置管理2024-12-12
SpringMVC通過攔截器實(shí)現(xiàn)IP黑名單
這篇文章主要為大家詳細(xì)介紹了SpringMVC通過攔截器實(shí)現(xiàn)IP黑名單,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2019-08-08
Java多線程并發(fā)編程 Volatile關(guān)鍵字
volatile 關(guān)鍵字是一個(gè)神秘的關(guān)鍵字,也許在 J2EE 上的 JAVA 程序員會(huì)了解多一點(diǎn),但在 Android 上的 JAVA 程序員大多不了解這個(gè)關(guān)鍵字。只要稍了解不當(dāng)就好容易導(dǎo)致一些并發(fā)上的錯(cuò)誤發(fā)生,例如好多人把 volatile 理解成變量的鎖2017-05-05
java發(fā)送郵件及打開狀態(tài)判斷分析實(shí)例
這篇文章主要為大家介紹了java發(fā)送郵件及打開狀態(tài)判斷分析實(shí)例2023-12-12
詳解java實(shí)現(xiàn)簡(jiǎn)單掃碼登錄功能(模仿微信網(wǎng)頁版掃碼)
這篇文章主要介紹了java實(shí)現(xiàn)簡(jiǎn)單掃碼登錄功能(模仿微信網(wǎng)頁版掃碼),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-05-05
SpringBoot配置 Druid 三種方式(包括純配置文件配置)
本文給大家分享在項(xiàng)目中用純 YML(application.yml 或者 application.properties)文件、Java 代碼配置 Bean 和注解三種方式配置 Alibaba Druid 用于監(jiān)控或者查看 SQL 狀況的相關(guān)知識(shí),感興趣的朋友一起看看吧2021-10-10
詳解Spring?Boot中@PostConstruct的使用示例代碼
在Java中,@PostConstruct是一個(gè)注解,通常用于標(biāo)記一個(gè)方法,它表示該方法在類實(shí)例化之后(通過構(gòu)造函數(shù)創(chuàng)建對(duì)象之后)立即執(zhí)行,這篇文章主要介紹了詳解Spring?Boot中@PostConstruct的使用,需要的朋友可以參考下2023-09-09

