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中无可用的对象时会遍历链表回收对象,实现了多线程之间对象回收的共享;

这里写图片描述

原创粉丝点击