Netty源码分析(七)—Recycler对象池分析
来源:互联网 发布:2016年网络作家排行榜 编辑:程序博客网 时间:2024/06/05 10:06
Netty源码分析(七)—Recycler对象池分析
Netty中实现轻量级的对象池技术,用来减少因为频繁的对象创建销毁而触发的内存分配和GC带来的性能消耗;Recycler是netty轻量级对象池的具体实现;
Netty使用ThreadLocal变量实现对象池的线程隔离进而实现对象池的无锁线程安全,相当于每个线程都维护着各自的小线程池
个人主页:tuzhenyu’s page
原文地址:Netty源码分析(七)—Recycler对象池分析
(0) Recycler使用实例
public class RecyclerTest { static class WrapRecycler{ private boolean tmp ; private final static Recycler<WrapRecycler> RECYCLER = new Recycler<WrapRecycler>() { @Override protected WrapRecycler newObject(Handle<WrapRecycler> handle) { return new WrapRecycler(handle); } }; Recycler.Handle<WrapRecycler> handle; WrapRecycler(Recycler.Handle<WrapRecycler> handle){ this.handle = handle; this.tmp = false; } static WrapRecycler getInstance(){ return RECYCLER.get(); } void recycle(){ this.tmp = false; handle.recycle(this); } public boolean getTmp(){ return tmp; } public void setTmp(boolean tmp){ this.tmp = tmp; } } public static void main(String[] args) { WrapRecycler instance = WrapRecycler.getInstance(); System.out.println(instance.hashCode()); System.out.println(instance.getTmp()); instance.setTmp(true); System.out.println(instance.getTmp()); instance.recycle(); instance = WrapRecycler.getInstance(); System.out.println(instance.hashCode()); System.out.println(instance.getTmp()); }}
- 运行结果,两次获取的对象的hashcode哈希值相同说明是同一个对象
41359092falsetrue41359092false
(1) Recycler类结构
Recycler是一个抽象类,在目标类中创建Recycler对象池实例时需要实现newObject(Handler handler)方法用来创建特定类的实例;
Recycler对象池内部是用一个对象数组维护对象池中的对象实例,对外提供统一的对象创建和回收接口:
Recycler#get方法 : 是获取对象池中对象的入口, 如果有可用对象,直接返回, 没有就调用newObject()方法创建一个.
Recycler#recycle方法: 是对象使用完毕后回收对象,只能回收当前线程创建的对象 现在已经标记@Deprecated不建议使用了, 建议使用Recycler.Handle#recycler方法,可以回收不是当前线程创建的对象, 复用性和性能更好了.
Recycler对象池的实现主要是通过三个核心组件:Handler,WeakOrderQueue和Stack
1. Handler组件
- Handler组件主要用来对外提供一个recycle()对象回收接口
static final class DefaultHandle<T> implements Handle<T> { private int lastRecycledId; private int recycleId; boolean hasBeenRecycled; private Stack<?> stack; private Object value; DefaultHandle(Stack<?> stack) { this.stack = stack; } @Override public void recycle(Object object) { if (object != value) { throw new IllegalArgumentException("object does not belong to handle"); } stack.push(this); }}
- 每个池化对象在newObject()创建时都会绑定一个Handler用作该对象的回收;
protected WrapRecycler newObject(Handle<WrapRecycler> handle) { return new WrapRecycler(handle);}
每个Handle关联一个value字段,用于存放具体的池化对象,在对象池中,所有的池化对象都被这个Handle包装,Handle是对象池管理的基本单位,Stack中存储管理的也是Handler类;
- 调用get()方法从对象池中获取复用对象,如果对象池为空则在stack中创建新的Handler实例,并通过newObject()方法创建对象赋给handler.value属性;
public final T get() { if (maxCapacityPerThread == 0) { return newObject((Handle<T>) NOOP_HANDLE); } Stack<T> stack = threadLocal.get(); DefaultHandle<T> handle = stack.pop(); if (handle == null) { handle = stack.newHandle(); handle.value = newObject(handle); } return (T) handle.value;}
2. Stack组件
- 通过FastThreadLocal类每个线程维护着一个与线程绑定的stack,用来存储复用的对象
private final FastThreadLocal<Stack<T>> threadLocal = new FastThreadLocal<Stack<T>>() { @Override protected Stack<T> initialValue() { return new Stack<T>(Recycler.this, Thread.currentThread(), maxCapacityPerThread, maxSharedCapacityFactor, ratioMask, maxDelayedQueuesPerThread); }};
- 线程在通过Recycler的get()方法获取复用对象时,首先获取与当前线程绑定的stack,再从Stack中pop出Handler包装实例
public final T get() { if (maxCapacityPerThread == 0) { return newObject((Handle<T>) NOOP_HANDLE); } Stack<T> stack = threadLocal.get(); DefaultHandle<T> handle = stack.pop(); if (handle == null) { handle = stack.newHandle(); handle.value = newObject(handle); } return (T) handle.value;}
3. WeakOrderQueue组件
- WeakOrderQueue是Recycler的一个内部私有类,用来暂存待回收的对象;Handler.recycler()可以回收不是当前线程创建的对象主要依靠WeakOrderQueue实现;
private static final FastThreadLocal<Map<Stack<?>, WeakOrderQueue>> DELAYED_RECYCLED = new FastThreadLocal<Map<Stack<?>, WeakOrderQueue>>() { @Override protected Map<Stack<?>, WeakOrderQueue> initialValue() { return new WeakHashMap<Stack<?>, WeakOrderQueue>(); }};
- 如果是当前线程创建的对象, 直接就把对象放到当前线程对应的Stack中. 如果不是, 则放入WeakOrderQueue中;每个线程维护着一个WeakHashmap
public void recycle(Object object) { if (object != value) { throw new IllegalArgumentException("object does not belong to handle"); } stack.push(this);}
void push(DefaultHandle<?> item) { Thread currentThread = Thread.currentThread(); if (thread == currentThread) { pushNow(item); } else { pushLater(item, currentThread); }}
private void pushLater(DefaultHandle<?> item, Thread thread) { Map<Stack<?>, WeakOrderQueue> delayedRecycled = DELAYED_RECYCLED.get(); WeakOrderQueue queue = delayedRecycled.get(this); if (queue == null) { if (delayedRecycled.size() >= maxDelayedQueues) { delayedRecycled.put(this, WeakOrderQueue.DUMMY); return; } if ((queue = WeakOrderQueue.allocate(this, thread)) == null) { return; } delayedRecycled.put(this, queue); } else if (queue == WeakOrderQueue.DUMMY) { return; } queue.add(item);}
- 在从Stack获取对象池时,如果Stack中可用对象为空,会尝试遍历多线程对应的WeakOrderQueue链表中回收恢复对象;
public final T get() { if (maxCapacityPerThread == 0) { return newObject((Handle<T>) NOOP_HANDLE); } Stack<T> stack = threadLocal.get(); DefaultHandle<T> handle = stack.pop(); if (handle == null) { handle = stack.newHandle(); handle.value = newObject(handle); } return (T) handle.value;}
DefaultHandle<T> pop() { int size = this.size; if (size == 0) { if (!scavenge()) { return null; } size = this.size; } size --; DefaultHandle ret = elements[size]; elements[size] = null; if (ret.lastRecycledId != ret.recycleId) { throw new IllegalStateException("recycled multiple times"); } ret.recycleId = 0; ret.lastRecycledId = 0; this.size = size; return ret;}
boolean scavengeSome() { WeakOrderQueue prev; WeakOrderQueue cursor = this.cursor; if (cursor == null) { prev = null; cursor = head; if (cursor == null) { return false; } } else { prev = this.prev; } boolean success = false; do { if (cursor.transfer(this)) { success = true; break; } WeakOrderQueue next = cursor.next; if (cursor.owner.get() == null) { if (cursor.hasFinalData()) { for (;;) { if (cursor.transfer(this)) { success = true; } else { break; } } } if (prev != null) { prev.setNext(next); } } else { prev = cursor; } cursor = next; } while (cursor != null && !success); this.prev = prev; this.cursor = cursor; return success;}
总结
Netty实现的轻量级的对象池实现了对象的复用和回收,核心组件包括Stack,WeakOrderQueue和Handler
Stack相当于MyBatis的一级缓存,与线程绑定,线程内对象的获取和回收都使用绑定的Stack;复用对象时直接从Stack中申请,使用完后如果对象是自己创建的则放入Stack;
在对象回收时候如果对象不是当前线程创建的则不能放入Stack中回收,而是放入WeakOrderQueue中,所有的Queue组成一个链表作为对象回收的仓库,当Stack中无可用的对象时会遍历链表回收对象,实现了多线程之间对象回收的共享;
- Netty源码分析(七)—Recycler对象池分析
- Netty源码 Recycler 对象池全面解析
- Netty源码分析(八)—内存池分析
- netty源码分析 之七 transport(Unsafe)
- netty-对象池实现Recycler用法测试
- Netty之轻量级对象池Recycler
- Netty源码分析(五)—ByteBuf源码分析
- netty源码分析(七)Acceptor与Dispatcher角色分析
- Netty 源码分析(一)
- Netty 源码分析(二)
- Netty 源码分析(三)
- Netty源码分析(四)—线程池EventLoopGroup源码分析
- Netty源码分析(六)—Future和Promis分析
- 【Netty4.X】Netty源码分析之ByteBuf(七)
- Netty 源码分析
- netty源码分析小结
- netty 源码分析一
- netty 源码分析二
- c语言练习题
- Python函数的用法总结
- 眼镜,回头,去不去?
- OpenCV010:以左右摄像头的拍摄图片为基础生成深度图
- 设计模式-外观模式
- Netty源码分析(七)—Recycler对象池分析
- Kalman滤波(一)
- Xposed框架初次见面-开发自己的Xposed插件
- Java单例设计模式的两种实现方式
- 使用const常量定义π,输出球的体积和表面积,球的半径r由键盘输入!
- CTF密码学(Crypto)一些在线解密网站
- CNN网络介绍与实践-王者荣耀英雄图片识别
- 使用cmake自动构建工程
- 一日一文(6)