Netty分布式从recycler对象回收站获取对象过程剖析

 更新时间:2022年03月29日 16:29:24   作者:向南是个万人迷  
这篇文章主要为大家介绍了Netty分布式从recycler获取对象的过程源码剖析,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪

前文传送门:Netty分布式高性能工具类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拿到我们实际使用的对象

以上就是从对象回收站获取对象的过程,更多关于Netty分布式recycler获取对象的资料请关注脚本之家其它相关文章!

相关文章

  • mybatis类型处理器JSR310标准详解

    mybatis类型处理器JSR310标准详解

    这篇文章主要介绍了mybatis类型处理器JSR310标准详解,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-01-01
  • Java多线程run方法中直接调用service业务类应注意的问题及解决

    Java多线程run方法中直接调用service业务类应注意的问题及解决

    这篇文章主要介绍了Java多线程run方法中直接调用service业务类应注意的问题及解决,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-06-06
  • spring cloud 使用Zuul 实现API网关服务问题

    spring cloud 使用Zuul 实现API网关服务问题

    这篇文章主要介绍了spring cloud 使用Zuul 实现API网关服务问题,非常不错,具有一定的参考借鉴价值,需要的朋友可以参考下
    2018-05-05
  • 使用@Transactional 设置嵌套事务不回滚

    使用@Transactional 设置嵌套事务不回滚

    这篇文章主要介绍了使用@Transactional 设置嵌套事务不回滚问题,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-07-07
  • javaSystem.out.println()输出byte[]、char[]异常的问题详析

    javaSystem.out.println()输出byte[]、char[]异常的问题详析

    这篇文章主要给大家介绍了关于javaSystem.out.println()输出byte[]、char[]异常问题的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面来一起看看啊
    2019-01-01
  • 带你了解Java数据结构和算法之队列

    带你了解Java数据结构和算法之队列

    这篇文章主要为大家介绍了Java数据结构和算法之队列,具有一定的参考价值,感兴趣的小伙伴们可以参考一下,希望能够给你带来帮助
    2022-01-01
  • SpringBoot详解MySQL如何实现读写分离

    SpringBoot详解MySQL如何实现读写分离

    当响应的瓶颈在数据库的时候,就要考虑数据库的读写分离,当然还可以分库分表,那是单表数据量特别大,当单表数据量不是特别大,但是请求量比较大的时候,就要考虑读写分离了.具体的话,还是要看自己的业务...如果还是很慢,那就要分库分表了...我们这篇就简单讲一下读写分离
    2022-09-09
  • Spring学习JdbcTemplate数据库事务参数

    Spring学习JdbcTemplate数据库事务参数

    这篇文章主要为大家介绍了Spring学习JdbcTemplate数据库事务参数使用示例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-05-05
  • idea引入外部jar包的方法实现

    idea引入外部jar包的方法实现

    本文主要介绍了idea引入外部jar包的方法实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2023-06-06
  • 解析Java中的定时器及使用定时器制作弹弹球游戏的示例

    解析Java中的定时器及使用定时器制作弹弹球游戏的示例

    这篇文章主要介绍了Java中的定时器及使用定时器制作弹弹球游戏的示例,文中同时也分析了定时器timer的缺点及相关替代方案,需要的朋友可以参考下
    2016-02-02

最新评论