Netty分布式高性能工具类同线程下回收对象解析

作者:向南是个万人迷 时间:2023-05-24 22:00:55 

同线程回收对象

上一小节剖析了从recycler中获取一个对象, 这一小节分析在创建和回收是同线程的前提下, recycler是如何进行回收的

回顾第三小节的demo中的main方法

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方法

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方法

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方法中:

void push(DefaultHandle<?> item) {
   Thread currentThread = Thread.currentThread();
   if (thread == currentThread) {
       pushNow(item);
   } else {
       pushLater(item, currentThread);
   }
}

这里首先判断当前线程, 和创建stack的时候保存的线程是否是同一线程, 如果是, 说明是同线程回收对象, 则执行pushNow方法将对象放入stack中

跟到pushNow方法中:

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, 我们跟进去:

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进行自增

来源:https://www.cnblogs.com/xiangnan6122/p/10209008.html

标签:Netty,分布式,同线程,对象回收
0
投稿

猜你喜欢

  • C#实现显示CPU使用率与内存使用率

    2022-09-26 15:03:58
  • java并发JUC工具包AtomicInteger原子整型语法基础

    2023-10-05 14:16:47
  • WinForm下 TextBox只允许输入数字的小例子

    2023-08-02 15:34:14
  • C#中把英文字母转换为大写或小写的方法

    2021-06-13 18:46:55
  • C#预处理器指令的用法实例分析

    2023-03-09 16:21:07
  • 使用jpa之动态插入与修改(重写save)

    2021-07-04 21:02:26
  • 浅谈java的守护线程与非守护线程

    2023-11-25 06:50:23
  • mybatis in查询条件过长的解决方案

    2022-06-08 12:44:14
  • Java8中对于LocalDateTime的序列化和反序列化问题

    2023-11-14 15:37:41
  • Springboot+Mybatis-plus不使用SQL语句进行多表添加操作及问题小结

    2021-09-30 10:31:10
  • Java八种基本变量作为类的成员变量的默认值操作

    2022-06-25 04:55:58
  • android实现横屏的代码及思路

    2023-06-25 09:35:40
  • SpringBoot2 Jpa 批量删除功能的实现

    2023-06-18 04:54:35
  • C# 如何调用C++ dll string类型返回

    2023-01-31 02:27:55
  • Java中的Map集合简单汇总解析

    2023-08-22 19:12:07
  • C# .NET 中的缓存实现详情

    2023-05-30 18:35:12
  • SpringBoot使用Maven插件进行项目打包的方法

    2022-12-21 21:07:34
  • Java8新特性之默认方法(default)浅析

    2023-10-03 10:41:13
  • java中重载、覆盖和隐藏三者的区别分析

    2021-09-30 22:16:48
  • C#创建安全的字典(Dictionary)存储结构

    2023-03-17 22:11:51
  • asp之家 软件编程 m.aspxhome.com