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裏通過數組存儲着回收的對象,構造方法如下圖:

對象的回收

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方法的邏輯:

Stack的pop方法
從其它線程獲取對象放到stack裏
  • 從其它線程獲取對象入口
  • 從其它線程攻取對象
  • 將Link集合裏的對象移到stack裏,邏輯如下圖:
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章