Netty Recycler原始碼解讀
Recycler是一個輕量級的物件快取池,用來實現物件的複用。下面是使用Recycler的一個簡單例項:
import io.netty.util.Recycler; public class RecycleTest { private static final Recycler<User> RECYCLER = new Recycler<User>() { //沒有物件的時候,新建一個物件, 會傳入一個handler,在Recycler池裡,所有的物件都會轉成DefaultHandle物件 @Override protected User newObject(Handle<User> handle) { return new User(handle); } }; private static class User { private final Recycler.Handle<User> handle; public User(Recycler.Handle<User> handle) { this.handle = handle; } public void recycle() { //通過handler進行物件的回收 handle.recycle(this); } } public static void main(String[] args) { User user = RECYCLER.get(); //直接呼叫user方法進行物件的回收 user.recycle(); User user1 = RECYCLER.get(); //這裡會返回true System.out.println(user1 == user); } }
Recycler物件的建立
Recycler內部通過FastThreadLocal裡的Stack棧來儲存物件池,每次通過get方法從池中得到物件的時候,先通過FastThreadLocal得到Stack物件,具體的引數含義如下圖所示:

Stack裡通過陣列儲存著回收的物件,構造方法如下圖:

Stack的構造方法
物件的回收
Recycler物件的回收會呼叫stack的push方法將物件放入到棧裡,這樣就完成了物件的回收,具體邏輯如下:

在push方法裡,根據執行緒的不同,又可以分為同線程的回收,與異執行緒的回收。
同線程物件的回收
執行緒的回收相對比較簡單,將物件放到Stack棧裡就完成了物件的回收,程式碼如下:

判斷物件是否回收的邏輯:

異執行緒物件的回收
異執行緒的回收是指建立物件的執行緒與呼叫recycler方法的執行緒不是同一個執行緒,這時候的回收邏輯就相對複雜了,裡面用到了兩個物件,分別為:
- WeakOrderQueue 儲存 其它執行緒回收到本執行緒的物件 ,當某個執行緒從Stack中獲取不到物件時會從WeakOrderQueue中獲取物件。每個執行緒的Stack擁有1個WeakOrderQueue連結串列,連結串列每個節點對應1個其它執行緒的WeakOrderQueue,其它執行緒回收到該Stack的物件就儲存在這個WeakOrderQueue裡。
- Link: WeakOrderQueue中包含1個Link連結串列,回收物件儲存在連結串列某個Link節點裡,當Link節點儲存的回收物件滿了時會新建1個Link放在Link連結串列尾, Link的容量為16 。
物件結構如下圖所示: -
獲取WeakOrderQueue
- 如果沒有相應的WeakOrderQueeu,則會建立WeakOrderQueue, 將建立執行緒的Stack與回收執行緒的WeakOrderQueue進行繫結,具體的程式碼如下:
-
將物件追加到WeakOrderQueue
- WeakOrderQueue的構造方法如下:
- Link構造方法
獲取一個物件
可以通過get方法從recycler物件裡獲取一個快取的物件,下面是get方法的邏輯:

Recycler的get方法邏輯
Stack的pop方法

從其它執行緒獲取物件放到stack裡
- 從其它執行緒獲取物件入口
- 從其它執行緒攻取物件
- 將Link集合裡的物件移到stack裡,邏輯如下圖: