Netty源码分析第8章(高性能工具类FastThreadLocal和Recycler)---->第5节: 同线程回收对象
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进行自增
以上就是同线程回收对象的逻辑
Netty源码分析第8章(高性能工具类FastThreadLocal和Recycler)---->第5节: 同线程回收对象的更多相关文章
- Netty源码分析第8章(高性能工具类FastThreadLocal和Recycler)---->第6节: 异线程回收对象
Netty源码分析第八章: 高性能工具类FastThreadLocal和Recycler 第六节: 异线程回收对象 异线程回收对象, 就是创建对象和回收对象不在同一条线程的情况下, 对象回收的逻辑 我 ...
- Netty源码分析第8章(高性能工具类FastThreadLocal和Recycler)---->第7节: 获取异线程释放的对象
Netty源码分析第八章: 高性能工具类FastThreadLocal和Recycler 第七节: 获取异线程释放的对象 上一小节分析了异线程回收对象, 原理是通过与stack关联的WeakOrder ...
- Netty源码分析第8章(高性能工具类FastThreadLocal和Recycler)---->第4节: recycler中获取对象
Netty源码分析第八章: 高性能工具类FastThreadLocal和Recycler 第四节: recycler中获取对象 这一小节剖析如何从对象回收站中获取对象: 我们回顾上一小节demo的ma ...
- Netty源码分析第8章(高性能工具类FastThreadLocal和Recycler)---->第1节: FastThreadLocal的使用和创建
Netty源码分析第八章: 高性能工具类FastThreadLocal和Recycler 概述: FastThreadLocal我们在剖析堆外内存分配的时候简单介绍过, 它类似于JDK的ThreadL ...
- Netty源码分析第8章(高性能工具类FastThreadLocal和Recycler)---->第2节: FastThreadLocal的set方法
Netty源码分析第八章: 高性能工具类FastThreadLocal和Recycler 第二节: FastThreadLocal的set方法 上一小节我们学习了FastThreadLocal的创建和 ...
- Netty源码分析第8章(高性能工具类FastThreadLocal和Recycler)---->第3节: recycler的使用和创建
Netty源码分析第八章: 高性能工具类FastThreadLocal和Recycler 第三节: recycler的使用和创建 这一小节开始学习recycler相关的知识, recycler是n ...
- Netty源码分析第3章(客户端接入流程)---->第1节: 初始化NioSockectChannelConfig
Netty源码分析第三章: 客户端接入流程 概述: 之前的章节学习了server启动以及eventLoop相关的逻辑, eventLoop轮询到客户端接入事件之后是如何处理的?这一章我们循序渐进, 带 ...
- Netty源码分析第3章(客户端接入流程)---->第2节: 处理接入事件之handle的创建
Netty源码分析第三章: 客户端接入流程 第二节: 处理接入事件之handle的创建 上一小节我们剖析完成了与channel绑定的ChannelConfig初始化相关的流程, 这一小节继续剖析客户端 ...
- Netty源码分析第3章(客户端接入流程)---->第3节: NioSocketChannel的创建
Netty源码分析第三章: 客户端接入流程 第三节: NioSocketChannel的创建 回到上一小节的read()方法: public void read() { //必须是NioEventLo ...
随机推荐
- Hadoop学习之路(三)Hadoop-2.7.5在CentOS-6.7上的编译
下载Hadoop源码 1.登录官网 2.确定你要安装的软件的版本 一个选取原则: 不新不旧的稳定版本 几个标准: 1)一般来说,刚刚发布的大版本都是有很多问题 2)应该选择某个大版本中的最后一个小版本 ...
- pom xml testng
<dependency> <groupId>org.testng</groupId> <artifactId>testng</artifactId ...
- PAT乙级1007
1007 素数对猜想 (20 分) 让我们定义dn为:dn=pn+1−pn,其中pi是第i个素数.显然有d1=1,且对于n>1有dn是偶数.“素数对猜想 ...
- zabbix 自定义key与参数Userparameters监控脚本输出
1.修改agent配置文件: 通过yum安装的zabbix-agent配置文件路径为/etc/zabbix/zabbix_agentd.conf 里面定义我们自己配置文件路径:Include=/etc ...
- Ember.NativeArray-原生数组
ember 2.18版本API翻译之Ember.NativeArray NativeArray mixin(混合类)包含使原生Array支持Ember.MutableArray 和其所有依赖API的属 ...
- block本质探寻六之修改变量
说明: <1>阅读本文章,请参照前面的block文章加以理解: <2>本文的变量指的是auto类型的局部变量(包括实例对象): <3>ARC和MRC两种模式均适用: ...
- vue watch关于对象内的属性监听
vue可以通过watch监听data内数据的变化.通常写法是: data: { a: 100 }, watch: { a(newval, oldVal) { // 做点什么... console.lo ...
- 阿里云CentOS自动备份MySql 8.0并上传至七牛云
本文主要介绍一下阿里云CentOS7下如何对MySql 8.0数据库进行自动备份,并使用.NET Core 将备份文件上传至七牛云存储上,并对整个过程所踩的坑加以记录. 环境.工具.准备工作 服务器: ...
- jQuery,js如何扩展自定义方法
(jQuery.fn.myMethod=function () { alert('myMethod'); }) (function ($) { $.fn.extend({ myMethod : fun ...
- MongoDB初学笔记(1)
学习目标 理解MongoDb的特点和体系结构 掌握常用的MongoDB命令 MongoDB是一种介于关系数据库和非关系数据库中的一种数据库.它支持的数据结构非常松散,类似于JSON的BJSOn格式,所 ...