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里,邏輯如下圖:
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容

  • 本節來看一下netty的Recycler對象池的設計與源碼解析。相關的源碼已經抽取為一個框架:https://gi...
    原水寒閱讀 4,497評論 1 17
  • 在netty的池化ByteBuf分配中,包含ByteBuf對象的池化和真實內存(array或者DirectByte...
    YDDMAX_Y閱讀 3,821評論 2 2
  • 從三月份找實習到現在,面了一些公司,掛了不少,但最終還是拿到小米、百度、阿里、京東、新浪、CVTE、樂視家的研發崗...
    時芥藍閱讀 42,341評論 11 349
  • Recycler用來實現對象池,其中對應堆內存和直接內存的池化實現分別是PooledHeapByteBuf和Poo...
    滄行閱讀 5,082評論 2 6
  • 在一個方法內部定義的變量都存儲在棧中,當這個函數運行結束后,其對應的棧就會被回收,此時,在其方法體中定義的變量將不...
    Y了個J閱讀 4,435評論 1 14