Netty源碼分析第8章(高性能工具類FastThreadLocal和Recycler)---->第5節: 同線程回收對象

 

Netty源碼分析第八章: 高性能工具類FastThreadLocal和Recyclerhtml

 

第五節: 同線程回收對象數組

 

上一小節剖析了從recycler中獲取一個對象, 這一小節分析在建立和回收是同線程的前提下, recycler是如何進行回收的工具

回顧第三小節的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); }

這裏就是一個同線程回收對象的典型場景, 在一個線程中將對象建立而且回收, 咱們的User對象定義了recycle方法性能

static class User{ private final Recycler.Handle<User> handle; public User(Recycler.Handle<User> handle){ this.handle=handle; } public void recycle(){ handle.recycle(this); } }

這裏的recycle是經過handle對象的recycle方法實現對象回收的, 這裏實際調用的是DefaultHandle的recycle方法this

咱們跟進recycle方法:spa

public void recycle(Object object) { if (object != value) { throw new IllegalArgumentException("object does not belong to handle"); } stack.push(this); }

這裏若是回收的對象爲null, 則拋出異常線程

若是不爲null, 則經過自身綁定stack的push方法將自身push到stack中code

跟到push方法中:htm

void push(DefaultHandle<?> item) { Thread currentThread = Thread.currentThread(); if (thread == currentThread) { pushNow(item); } else { pushLater(item, currentThread); } }

這裏首先判斷當前線程, 和建立stack的時候保存的線程是不是同一線程, 若是是, 說明是同線程回收對象, 則執行pushNow方法將對象放入stack中

跟到pushNow方法中:

private void pushNow(DefaultHandle<?> item) { if ((item.recycleId | item.lastRecycledId) != 0) { throw new IllegalStateException("recycled already"); } item.recycleId = item.lastRecycledId = OWN_THREAD_ID; int size = this.size; if (size >= maxCapacity || dropHandle(item)) { return; } if (size == elements.length) { elements = Arrays.copyOf(elements, min(size << 1, maxCapacity)); } elements[size] = item; this.size = size + 1; }

若是第一次回收, item.recycleId和item.lastRecycledId都爲0, 因此不會進入if塊, 咱們繼續往下看

 item.recycleId = item.lastRecycledId = OWN_THREAD_ID 這一步將handle的recycleId和lastRecycledId賦值爲OWN_THREAD_ID, OWN_THREAD_ID在每個recycle中是惟一固定的, 這裏咱們只須要記得這個概念就行

而後獲取當前size

若是size超過上限大小, 則直接返回

這裏還有個判斷dropHandle, 咱們跟進去:

boolean dropHandle(DefaultHandle<?> handle) { if (!handle.hasBeenRecycled) { if ((++handleRecycleCount & ratioMask) != 0) { return true; } handle.hasBeenRecycled = true; } return false; }

 if (!handle.hasBeenRecycled) 表示當前對象以前是否沒有被回收過, 若是是第一次回收, 這裏會返回true, 而後進入放到if

再看if中的判斷 if ((++handleRecycleCount & ratioMask) != 0) 

handleRecycleCount表示當前位置stack回收了多少次對象(回收了多少次, 不表明回收了多少個對象, 由於不是每次回收都會被成功的保存在stack), ratioMask咱們以前分析過是7, 這裏 (++handleRecycleCount & ratioMask) != 0 表示回收的對象數若是不是8的倍數, 則返回true, 表示只回收1/8的對象

而後將hasBeenRecycled設置爲true, 表示已經被回收

回到pushNow方法中:

若是size的大小等於stack中的數組elements的大小, 則將數組elements進行擴容

最後將size經過數組下標的方式將當前handle設置到elements的元素中, 並將size進行自增

以上就是同線程回收對象的邏輯

 

上一節: reclycer中獲取對象

下一節: 異線程回收對象

相關文章
相關標籤/搜索