前言
netty学习系列笔记总结,轻量级对象池-Recycler源码浅析,错误之处欢迎指正, 共同学习
介绍
由于Java 创建一个实例的消耗不小,所以现在很多框架都使用对象池。创建对象的时候不需要每次都通过new方式创建,如果Recycler有对象直接获取二次利用,不需要对象的时候放入Recycler对象池。通过重用对象,能够避免频繁创建对象和销毁对象带来的损耗。
Recycler的使用
定义基于 FastThreadLocal 的轻量级对象池 Recycler 负责对象的回收和二次利用,不需要每次分配内存减少内存使用,减少 new 对象频率即减少 Young GC 频率
创建对象通过 Recycler 的 get() 获取对象池里面的对象,不需要对象时可以显式调用 recycle() 方法回收对象放到对象池
通过自定义 newObject() 方法定义对象创建,参数handle负责对象回收到对象池Recycler
1 | private static final Recycler<User> RECYCLER = new Recycler<User>() { |
执行结果如下
1 | true |
Recycler的创建
1 | protected Recycler() { |
Recycler成员变量FastThreadLocal<Stack
Recycler中获取对象
- 获取当前线程的Stack
- 从Stack里面弹出DefaultHandle对象
- 创建对象并绑定到Stack
1 | public final T get() { |
回收对象到Recycler
- 同线程回收对象
- 异线程回收对象
同线程回收对象
1 | public void recycle(Object object) { |
回收对象到Recycler:
调用Handle的recycle()方法回收对象,使用Stack的push()方法把当前对象压入栈里面,判断当前线程是否为创建Stack的thread执行同/异线程回收对象
1.同线程回收对象->stack.pushNow()
设置recycleId/lastRecycledId为OWN_THREAD_ID,当前Stack对象数量超过承载最大容量或者Handle没有被回收过并且回收对象数量+1&对象回收频率不等于0即回收1/8对象则丢弃对象,当前Stack对象数量达到数组容量则重新创建2倍Stack对象数量的数组,赋值数组当前Stack对象数量位置为回收对象
异线程回收对象
- 获取WeakOrderQueue
- 创建WeakOrderQueue
- 将对象追加到WeakOrderQueue
回收对象到Recycler:
2.异线程回收对象->stack.pushLater()
(1)获取WeakOrderQueue->DELAYED_RECYCLED.get()
通过当前Stack对象获取delayedRecycled的WeakOrderQueue
(2)创建WeakOrderQueue->WeakOrderQueue.allocate()
把WeakOrderQueue插入到Stack对象头部实现当前线程分配Stack对象
(3)将对象追加到WeakOrderQueue->queue.add()
将DefaultHandle对象追加到尾指针tail的elements数组
1 | private void pushLater(DefaultHandle<?> item, Thread thread) { |
异线程收割对象
- 获取当前线程的Stack
- 从Stack里面弹出对象
- 创建对象并绑定到Stack
异线程收割对象->stack.scavenge()从其他线程回收对象
使用scavengeSome()方法获取当前需要回收WeakOrderQueue cursor,while循环向当前Stack关联的WeakOrderQueue回收对象,使用WeakOrderQueue cursor的transfer()方法把WeakOrderQueue的Link传输到Stack,循环将当前Link数组元素传输到当前Stack底层数组,cursor的关联线程owner是否为空释放cursor节点,如果没有回收到对象则重置prev指针置为空/cursor指针置为head头节点即下次从头部开始回收