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進行自增
以上就是同線程回收對象的邏輯