同线程回收对象
上一小节剖析了从recycler中获取一个对象, 这一小节分析在创建和回收是同线程的前提下, recycler是如何进行回收的
回顾第三小节的demo中的main方法
1 2 3 4 5 6 7 |
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方法
1 2 3 4 5 6 7 8 9 |
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方法
我们跟进recycle方法
1 2 3 4 5 6 |
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中
跟到push方法中:
1 2 3 4 5 6 7 8 |
void push(DefaultHandle<?> item) { Thread currentThread = Thread.currentThread(); if (thread == currentThread) { pushNow(item); } else { pushLater(item, currentThread); } } |
这里首先判断当前线程, 和创建stack的时候保存的线程是否是同一线程, 如果是, 说明是同线程回收对象, 则执行pushNow方法将对象放入stack中
跟到pushNow方法中:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
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, 我们跟进去:
1 2 3 4 5 6 7 8 9 |
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进行自增
以上就是同线程回收对象的逻辑,更多关于Netty分布式同线程回收对象的资料请关注其它相关文章!
原文链接:https://HdhCmsTestcnblogs测试数据/xiangnan6122/p/10209008.html
查看更多关于Netty分布式高性能工具类同线程下回收对象解析的详细内容...