Netty源码分析第八章: 高性能工具类FastThreadLocal和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);
}

这个通过Recycler的get方法获取对象, 我们跟到get方法中:

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;
}

首先判断maxCapacityPerThread是否为0, maxCapacityPerThread代表stack最多能缓存多少个对象, 如果缓存0个, 说明对象将一个都不会回收

这个通过调用newObject创建一个对象, 并传入一个NOOP_HANDLE, NOOP_HANDLE是一个handle, 我们看其定义:

private static final Handle NOOP_HANDLE = new Handle() {
@Override
public void recycle(Object object) { }
};

这里的recycle方法是一个空实现, 代表不进行任何对象回收

回到get方法中:

我们看第二步 Stack<T> stack = threadLocal.get();

这里通过FastThreadLocal对象拿到当前线程的stack, 有关FastThreadLocal获取对象的逻辑之前小节剖析过, 这里不再赘述

获取stack之后, 从stack中pop出一个handle, 这个handle做用我们稍后分析

如果取出的对象为null, 说明当前回收站内没有任何对象, 通常第一次执行到这里对象还没回收, 这里就会是null, 这样则会通过stack.newHandle()创建一个handle

创建出来的handle的value属性, 通过我们重写的newObject方法进行赋值, 也就是我们demo中的user

我们跟进newHandle方法:

DefaultHandle<T> newHandle() {
return new DefaultHandle<T>(this);
}

这里创建一个DefaultHandle对象, 并传入this, 这里的this是当前stack

跟到DefaultHandle的构造方法中:

DefaultHandle(Stack<?> stack) {
this.stack = stack;
}

这里初始化了stack属性

DefaultHandle中还有个value的成员变量

private Object value;

这里的value就用来绑定回收的对象本身

回到get方法中:

分析handle, 我们回到上一步:

DefaultHandle<T> handle = stack.pop();

我们分析从stack中弹出一个handle的逻辑

跟到pop方法中:

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;
}

首先拿到size, size表示当前stack的对象数

如果size为0, 则调用scavenge方法, 这个方法是异线程回收对象的方法, 我们放在之后的小节进行分析

size大于零, 则size进行自减, 代表取出一个元素

然后通过size的数组下标的方式将handle取出

之后将当前下标设置为null

最后将属性recycleId, lastRecycledId, size进行赋值

recycleId和lastRecycledId我们会在之后的小节进行分析

回到get方法中:

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;
}

无论是从stack中弹出的handle, 还是创建的handle, 最后都要通过handle.value拿到我们实际使用的对象

以上就是从对象回收站获取对象的过程

上一节: recycler的使用和创建

下一节: 同线程回收对象

Netty源码分析第8章(高性能工具类FastThreadLocal和Recycler)---->第4节: recycler中获取对象的更多相关文章

  1. Netty源码分析第8章(高性能工具类FastThreadLocal和Recycler)---->第1节: FastThreadLocal的使用和创建

    Netty源码分析第八章: 高性能工具类FastThreadLocal和Recycler 概述: FastThreadLocal我们在剖析堆外内存分配的时候简单介绍过, 它类似于JDK的ThreadL ...

  2. Netty源码分析第8章(高性能工具类FastThreadLocal和Recycler)---->第7节: 获取异线程释放的对象

    Netty源码分析第八章: 高性能工具类FastThreadLocal和Recycler 第七节: 获取异线程释放的对象 上一小节分析了异线程回收对象, 原理是通过与stack关联的WeakOrder ...

  3. Netty源码分析第8章(高性能工具类FastThreadLocal和Recycler)---->第2节: FastThreadLocal的set方法

    Netty源码分析第八章: 高性能工具类FastThreadLocal和Recycler 第二节: FastThreadLocal的set方法 上一小节我们学习了FastThreadLocal的创建和 ...

  4. Netty源码分析第8章(高性能工具类FastThreadLocal和Recycler)---->第3节: recycler的使用和创建

    Netty源码分析第八章: 高性能工具类FastThreadLocal和Recycler 第三节: recycler的使用和创建   这一小节开始学习recycler相关的知识, recycler是n ...

  5. Netty源码分析第8章(高性能工具类FastThreadLocal和Recycler)---->第5节: 同线程回收对象

    Netty源码分析第八章: 高性能工具类FastThreadLocal和Recycler 第五节: 同线程回收对象 上一小节剖析了从recycler中获取一个对象, 这一小节分析在创建和回收是同线程的 ...

  6. Netty源码分析第8章(高性能工具类FastThreadLocal和Recycler)---->第6节: 异线程回收对象

    Netty源码分析第八章: 高性能工具类FastThreadLocal和Recycler 第六节: 异线程回收对象 异线程回收对象, 就是创建对象和回收对象不在同一条线程的情况下, 对象回收的逻辑 我 ...

  7. Netty源码分析第3章(客户端接入流程)---->第1节: 初始化NioSockectChannelConfig

    Netty源码分析第三章: 客户端接入流程 概述: 之前的章节学习了server启动以及eventLoop相关的逻辑, eventLoop轮询到客户端接入事件之后是如何处理的?这一章我们循序渐进, 带 ...

  8. Netty源码分析第3章(客户端接入流程)---->第2节: 处理接入事件之handle的创建

    Netty源码分析第三章: 客户端接入流程 第二节: 处理接入事件之handle的创建 上一小节我们剖析完成了与channel绑定的ChannelConfig初始化相关的流程, 这一小节继续剖析客户端 ...

  9. Netty源码分析第3章(客户端接入流程)---->第3节: NioSocketChannel的创建

    Netty源码分析第三章: 客户端接入流程 第三节: NioSocketChannel的创建 回到上一小节的read()方法: public void read() { //必须是NioEventLo ...

随机推荐

  1. ARC与Toll-Free Bridging

    arc模块与mrc模块的沟通. 相当于程序的混编处理. Toll-Free Briding保证了在程序中,可以方便和谐的使用Core Foundation类型的对象和Objective-C类型的对象. ...

  2. 20145203盖泽双 《Java程序设计》第五周学习总结

    20145203盖泽双 <Java程序设计>第五周学习总结 教材学习内容总结 1.Java中所有错误都会被打包为对象,运用try.catch,可以在错误发生时显示友好的错误信息,还可以在捕 ...

  3. 改变文件上传input file类型的外观

    当我们使用文件上传功能时,<input type="file">,但是外观有点不符合口味,如何解决这个问题? <input type="file&quo ...

  4. @SpringBootApplication无法被解析引入

    问题描述:@SpringBootApplication无法被解析引入,导致SpringBoot启动类报错 原因分析:springboot的包冲突了所致 解决方案: 需要删掉 repository\or ...

  5. python pyspark入门篇

    一.环境介绍: 1.安装jdk 7以上 2.python 2.7.11 3.IDE pycharm 4.package: spark-1.6.0-bin-hadoop2.6.tar.gz 二.Setu ...

  6. P1877 [HAOI2012]音量调节

    题目描述 一个吉他手准备参加一场演出.他不喜欢在演出时始终使用同一个音量,所以他决定每一首歌之前他都需要改变一次音量.在演出开始之前,他已经做好一个列表,里面写着每首歌开始之前他想要改变的音量是多少. ...

  7. 初次接触ARM开发,理清这四个开发思路很重要!

    初次接触ARM开发,理清这四个开发思路很重要! 由于涉及编程,学习ARM单片机系统对于从事电子电路的设计者来说是有些困难的,学习知识不难,难的是理清其中的开发思路,找到一个好的起点.本文就将从这一步入 ...

  8. Hadoop(18)-MapReduce框架原理-WritableComparable排序和GroupingComparator分组

    1.排序概述 2.排序分类 3.WritableComparable案例 这个文件,是大数据-Hadoop生态(12)-Hadoop序列化和源码追踪的输出文件,可以看到,文件根据key,也就是手机号进 ...

  9. rails使用Kindeditor网页编辑器

    在gemfile中加入(后面版本别丢) gem 'rails_kindeditor', '~> 0.5.0' $ bundle 创建配置文件,并且引入js rails g rails_kinde ...

  10. C语言学习记录_2019.02.09

    打印字符串:%s--------printf("%s","abcd"); 打印字符串数组中某一位:%c--------printf("%c" ...