Netty源码分析第八章: 高性能工具类FastThreadLocal和Recycler

第五节: 同线程回收对象

上一小节剖析了从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进行自增

以上就是同线程回收对象的逻辑

上一节: reclycer中获取对象

下一节: 异线程回收对象

最新文章

  1. inline-block元素vertical-align的问题分析
  2. C语言教学--二维数组和指针的理解
  3. 单用户模式下连接被占用定位spid
  4. uva 122 trees on the level——yhx
  5. PC-飞起来!我的Windows XP——五步快速优化Windows XP
  6. python 笔记3--高级特性
  7. 让我的分页类获取sessionFactory
  8. sparklyr包:实现Spark与R的接口
  9. 什么样的简历受HR青睐?
  10. iOS 中判断应用程序是否为第一次打开
  11. iphone屏幕镜像怎么用 手机投屏电脑
  12. Vusial Studio连接不到源代码管理器Vss
  13. 分布式系统缓存系列之guava cache
  14. c# pictureBox1.Image的获得图片路径的三种方法 winform
  15. Django的CBV的学习
  16. lamp环境服务器配置文档
  17. HTML5无刷新修改URL
  18. Tensorflow從源碼編譯
  19. 对HashMap的理解(三):ConcurrentHashMap
  20. hdu 3949 第k大异或组合

热门文章

  1. log4j配置不生效
  2. HashMap实现原理及源码分析之JDK8
  3. jenkins 构建触发器 Poll SCM 和 Build periodically区别
  4. CSU 1547: Rectangle (思维题加一点01背包)
  5. MapReduce -- 统计天气信息
  6. 原型和原型对象(__proto__和prototype)转
  7. 关于mysql-mybatis批量添加
  8. python 第一课作用
  9. C 共享内存封装
  10. 从0开始学golang--1.1--连接ms sql server数据库