netty原始碼閱讀之效能優化工具類之Recycler獲取物件
Recycler獲取物件主要分為以下幾部分:
1、獲取當前執行緒的Stack
2、從Stack裡面彈出物件
3、如果彈出物件為空,那就建立物件並且繫結到Stack裡面
我們從Recycler的get方法進入,就是這個原始碼:
@SuppressWarnings("unchecked") 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這個分支,看NOOP_HANDLE這個原始碼:
@SuppressWarnings("rawtypes")
private static final Handle NOOP_HANDLE = new Handle() {
@Override
public void recycle(Object object) {
// NOOP
}
};
recycle的時候,什麼是都不做。
也就是,如果maxCapacityPerThread為0,我們就什麼物件都不快取。
一、獲取當前執行緒的Stack
就是這段程式碼:
Stack<T> stack = threadLocal.get();
獲取當前執行緒的stack。
threadLocal就是FastThreadLocal:
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); } };
初始化的時候,會新建一個stack。
二、從Stack裡面彈出物件
這個物件就是pop物件。
DefaultHandle<T> handle = stack.pop();
pop出來的物件是一個handle,物件就存在handle裡面,也就是要返回的就是handle.value。
然後我們分析pop的過程:
@SuppressWarnings({ "unchecked", "rawtypes" })
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裡面有多少個物件。如果size等於0,就會呼叫scavenge(),意思就是如果當前執行緒沒有物件了,但是我的物件有可能在別的執行緒那裡有物件,就去別的執行緒那裡找,後面再分析這個方法。
後續如果size不為0,那就從stack裡面取,size--。
DefaultHandle ret = elements[size]; elements[size] = null;就是把物件取出來並且設定原來的物件為null。
然後:
ret.recycleId = 0;
ret.lastRecycledId = 0;
這兩段程式碼的意思就是,物件被使用了,並沒有在回收次裡面。
三、建立物件並且繫結到Stack裡面
這一段原始碼就是我們這裡要分析的內容:
if (handle == null) {
handle = stack.newHandle();
handle.value = newObject(handle);
}
handle為空,就在stack裡面新建一個handle:
DefaultHandle<T> newHandle() {
return new DefaultHandle<T>(this);
}
這個handle是DefaultHandle並且把this傳入進去,這個this就是stack:
DefaultHandle(Stack<?> stack) {
this.stack = stack;
}
也就是每個handle都綁定了一個stack。
最後handle.value=newObject(handle)就是我們要的物件,這裡也不是很複雜。