netty 性能,netty高级应用

  netty 性能,netty高级应用

  00-1010使用回收器这里有一个例子。在Recycler的类的源代码中,我们看到这段逻辑遵循了Stack的构造方法,我们又回到了Stack的构造方法。前一个门户:Netty分布式FastThreadLocal的set方法实现逻辑分析。

  00-1010这一节开始学习recycler,这是netty实现的轻量级对象回收站。在netty中,经常使用recycler。

  回收器的作用是保证对象的回收,被使用后可以被回收器回收,需要再次使用时从对象池中取出。不需要每次都创建新的对象,减少了系统资源的占用和gc的压力。

  

目录

公共类RECYCLER demo { private static final recycle ruser RECYCLER=new recycle ruser(){ @ Override protected User new object(handle User handle){ return new User(handle);} };静态类用户{私有最终回收器。handle用户句柄;公共用户(回收者。handle user handle){ this . handle=handle;} public void recycle(){ handle . recycle(this);} }公共静态void main(String[]args){ User User 1=recycler . get();user 1 . recycle();用户user 2=recycler . get();user 2 . recycle();system . out . println(user 1==user 2);}}首先定义了RECYCLER的一个成员变量Recycler,在匿名内部类中重写了newObject方法,也就是创建对象的方法,匿名内部类是用户自定义的。

 

  这里newObject返回的新用户(句柄)是指当回收站中没有这样的对象时,可以这样创建对象。

  成员变量回收器可用于回收和重用此类对象。

  定义了一个静态内部类user,user中有一个成员变量handle,在构造方法中赋值。句柄的作用是回收对象。

  并定义了一个方法recycle,在方法体中通过handle.recycle(this)的方式回收对象本身。通过此操作,对象可以被回收到回收器。

  先了解以上逻辑,再详细分析。

  在main方法中,通过回收器的get方法获取一个用户,然后回收。

  然后通过get方法取出回收站中的对象,再次回收,最后判断两次取出的对象是否为对象,最终结果为真。

  上面的演示可以说明Recycler的回收功能。

  简单介绍了demo之后,我们再详细分析一下Recycler的机制。

  

recycler的使用

private final FastThreadLocalStackT thread local=new FastThreadLocalStackT(){ @ Override protected stack initial value(){ return new stack(recycler . this,Thread.currentThread(),maxCapacityPerThread,maxSharedCapacityFactor,ratioMask,maxDelayedQueuesPerThread);}};这个逻辑我们并不陌生。在上一节的学习中,我们知道它是用来存储线程共享对象的,这里的共享对象是一个栈类型的对象。

 

  每个堆栈维护一个DefaultHandle类型的数组,用于保存回收的对象。关于堆栈

  和线程的关系如图所示:

  

 

  8-3-1

  也就是说在每个Recycler中,都维护着一个线程共享的栈,用于对一类对象的回收

  

 

  

跟到Stack的构造方法中

Stack(Recycler<T> parent, Thread thread, int maxCapacity, int maxSharedCapacityFactor, int ratioMask, int maxDelayedQueues) { this.parent = parent; this.thread = thread; this.maxCapacity = maxCapacity; availableSharedCapacity = new AtomicInteger(max(maxCapacity / maxSharedCapacityFactor, LINK_CAPACITY)); elements = new DefaultHandle[min(INITIAL_CAPACITY, maxCapacity)]; this.ratioMask = ratioMask; this.maxDelayedQueues = maxDelayedQueues;}

首先介绍几个构造方法中初始化的关键属性:

 

  属性parent表示Reclycer对象自身

  属性thread表示当前stack绑定的哪个线程

  属性maxCapacity表示当前stack的最大容量,表示stack最多能盛放多少个元素

  属性elements,就表示stack中存储的对象,类型为DefaultHandle,可以被外部对象引用,从而实现回收

  属性ratioMask是用来控制对象回收的频率的,也就是说每次通过Reclycer回收对象的时候,不是每次都会进行回收,而是通过该参数控制回收频率

  属性maxDelayedQueues,这里稍微有些复杂,在很多时候,一个线程创建的对象,有可能会被另一个线程所释放,而另一个线程释放的对象是不会放在当前线程的stack中的,而是会存放在一个叫做WeakOrderQueue的数据结构中,里面也是存放着一个个DefaultHandle, WeakOrderQueue会存放线程1创建的并且在线程2进行释放的对象

  这里只是稍作了解,之后的会对此做详细剖析,这里我们只需知道, maxDelayedQueues属性的意思就是我这个线程能回收几个其他创建的对象的线程, 假设当前线程是线程1,maxDelayedQueues为2, 那么我线程1回收了线程2创建的对象, 又回收了线程3创建的对象, 那么不可能回收线程4创建的对象了, 因为maxDelayedQueues2, 我只能回收两个线程创建的对象

  属性availableSharedCapacity,表示在线程1中创建的对象,在其他线程中缓存的最大个数,同样,相关逻辑会在之后的内容进行剖析

  另外介绍两个没有在构造方法初始化的属性:

  

private WeakOrderQueue cursor, prev;private volatile WeakOrderQueue head;

这里相当于指针,用于指向WeakOrderQueue的,这里也是稍作了解,之后会进行详细剖析

 

  有关stack异线程之间对象的关系如图所示(简略):

  

 

  8-3-2

  我们再继续介绍Recycler的构造方法,同时熟悉有关stack各个参数的默认值:

  

protected Recycler() { this(DEFAULT_MAX_CAPACITY_PER_THREAD);}

这里调用了重载的构造方法,并传入了参数DEFAULT_MAX_CAPACITY_PER_THREAD

 

  DEFAULT_MAX_CAPACITY_PER_THREAD的默认值是32768,在static块中被初始化的,我们可以跟进去自行分析

  这个值就代表的每个线程中, stack中最多回收的元素的个数

  

 

  

继续跟重载的构造方法

protected Recycler(int maxCapacityPerThread) { this(maxCapacityPerThread, MAX_SHARED_CAPACITY_FACTOR);}

这里又调用了重载的构造方法,并且传入刚才传入的32768和MAX_SHARED_CAPACITY_FACTOR

 

  MAX_SHARED_CAPACITY_FACTOR默认值是2,同样在static块中进行了初始化,有关该属性的用处稍后讲解

  继续跟构造方法:

  

protected Recycler(int maxCapacityPerThread, int maxSharedCapacityFactor) { this(maxCapacityPerThread, maxSharedCapacityFactor, RATIO, MAX_DELAYED_QUEUES_PER_THREAD);}

这里同样调用了重载的构造方法,传入了刚才32768和2,还有两个属性RATIO和MAX_DELAYED_QUEUES_PER_THREAD

 

  RATIO也在static中被初始化,默认值是8

  同上, MAX_DELAYED_QUEUES_PER_THREAD的默认值是2倍cpu核数

  我们继续跟构造方法:

  

protected Recycler(int maxCapacityPerThread, int maxSharedCapacityFactor, int ratio, int maxDelayedQueuesPerThread) { ratioMask = safeFindNextPositivePowerOfTwo(ratio) - 1; if (maxCapacityPerThread <= 0) { this.maxCapacityPerThread = 0; this.maxSharedCapacityFactor = 1; this.maxDelayedQueuesPerThread = 0; } else { this.maxCapacityPerThread = maxCapacityPerThread; this.maxSharedCapacityFactor = max(1, maxSharedCapacityFactor); this.maxDelayedQueuesPerThread = max(0, maxDelayedQueuesPerThread); }}

这里将几个属性进行了初始化

 

  首先看ratioMask,这里的方法safeFindNextPositivePowerOfTwo的参数ratio为8,该方法的意思就是大于等于8的2的幂次方-1,这里就是ratioMask就是7

  

maxCapacityPerThread是刚才分析的32768,是一个大于0的数,所以进入else

 

  maxCapacityPerThread为32768

  maxSharedCapacityFactor的值为2

  maxDelayedQueuesPerThread的值为2倍CPU核数

  

 

  

我们再回到Stack的构造方法中

Stack(Recycler<T> parent, Thread thread, int maxCapacity, int maxSharedCapacityFactor, int ratioMask, int maxDelayedQueues) { this.parent = parent; this.thread = thread; this.maxCapacity = maxCapacity; availableSharedCapacity = new AtomicInteger(max(maxCapacity / maxSharedCapacityFactor, LINK_CAPACITY)); elements = new DefaultHandle[min(INITIAL_CAPACITY, maxCapacity)]; this.ratioMask = ratioMask; this.maxDelayedQueues = maxDelayedQueues;}

根据Recycler初始化属性的逻辑,我们可以知道Stack中几个属性的值:

 

  

maxCapacity默认值为32768

 

  ratioMask默认值为7

  maxDelayedQueues默认值是两倍cpu核数

  availableSharedCapacity的默认值是32768/2,也就是16384

  

以上就是Recycler创建的相关逻辑,更多关于Netty分布式工具类recycler使用的资料请关注盛行IT其它相关文章!

 

郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。

留言与评论(共有 条评论)
   
验证码: