Netty分布式從recycler對象回收站獲取對象過程剖析
前文傳送門:Netty分布式高性能工具類recycler的使用及創(chuàng)建
從對象回收站中獲取對象
我們回顧上一小節(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);
}這個通過Recycler的get方法獲取對象, 我們跟到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最多能緩存多少個對象, 如果緩存0個, 說明對象將一個都不會回收
這個通過調用newObject創(chuàng)建一個對象, 并傳入一個NOOP_HANDLE, NOOP_HANDLE是一個handle, 我們看其定義:
private static final Handle NOOP_HANDLE = new Handle() {
@Override
public void recycle(Object object) {
}
};這里的recycle方法是一個空實現(xiàn), 代表不進行任何對象回收
回到get方法中
我們看第二步
Stack<T> stack = threadLocal.get();
這里通過FastThreadLocal對象拿到當前線程的stack, 有關FastThreadLocal獲取對象的邏輯之前小節(jié)剖析過, 這里不再贅述
獲取stack之后, 從stack中pop出一個handle, 這個handle做用我們稍后分析
如果取出的對象為null, 說明當前回收站內沒有任何對象, 通常第一次執(zhí)行到這里對象還沒回收, 這里就會是null, 這樣則會通過stack.newHandle()創(chuàng)建一個handle
創(chuàng)建出來的handle的value屬性, 通過我們重寫的newObject方法進行賦值, 也就是我們demo中的user
我們跟進newHandle方法
DefaultHandle<T> newHandle() {
return new DefaultHandle<T>(this);
}這里創(chuàng)建一個DefaultHandle對象, 并傳入this, 這里的this是當前stack
跟到DefaultHandle的構造方法中:
DefaultHandle(Stack<?> stack) {
this.stack = stack;
}這里初始化了stack屬性
DefaultHandle中還有個value的成員變量
private Object value;
這里的value就用來綁定回收的對象本身
回到get方法中:
分析handle, 我們回到上一步:
DefaultHandle<T> handle = stack.pop();
我們分析從stack中彈出一個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表示當前stack的對象數(shù)
如果size為0, 則調用scavenge方法, 這個方法是異線程回收對象的方法, 我們放在之后的小節(jié)進行分析
size大于零, 則size進行自減, 代表取出一個元素
然后通過size的數(shù)組下標的方式將handle取出
之后將當前下標設置為null
最后將屬性recycleId, lastRecycledId, size進行賦值
recycleId和lastRecycledId我們會在之后的小節(jié)進行分析
回到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拿到我們實際使用的對象
以上就是從對象回收站獲取對象的過程,更多關于Netty分布式recycler獲取對象的資料請關注腳本之家其它相關文章!
相關文章
SpringBoot使用Nacos進行application.yml配置管理
Nacos是阿里巴巴開源的一個微服務配置管理和服務發(fā)現(xiàn)的解決方案,它提供了動態(tài)服務發(fā)現(xiàn)、配置管理和?服務管理平臺,Nacos使用Raft協(xié)議保證配置的一致性,同時支持多種配置?格式,如properties、yaml等,本文介紹了SpringBoot使用Nacos進行application.yml配置管理2024-12-12
詳解java實現(xiàn)簡單掃碼登錄功能(模仿微信網頁版掃碼)
這篇文章主要介紹了java實現(xiàn)簡單掃碼登錄功能(模仿微信網頁版掃碼),文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2019-05-05
SpringBoot配置 Druid 三種方式(包括純配置文件配置)
本文給大家分享在項目中用純 YML(application.yml 或者 application.properties)文件、Java 代碼配置 Bean 和注解三種方式配置 Alibaba Druid 用于監(jiān)控或者查看 SQL 狀況的相關知識,感興趣的朋友一起看看吧2021-10-10
詳解Spring?Boot中@PostConstruct的使用示例代碼
在Java中,@PostConstruct是一個注解,通常用于標記一個方法,它表示該方法在類實例化之后(通過構造函數(shù)創(chuàng)建對象之后)立即執(zhí)行,這篇文章主要介紹了詳解Spring?Boot中@PostConstruct的使用,需要的朋友可以參考下2023-09-09

