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

 更新时间:2022年03月29日 16:43:28   作者:向南是个万人迷  
这篇文章主要为大家介绍了Netty分布式高性能工具类同线程下回收对象解析,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪

同线程回收对象

上一小节剖析了从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分布式同线程回收对象的资料请关注脚本之家其它相关文章!

相关文章

  • 实例讲解Java 自旋锁

    实例讲解Java 自旋锁

    这篇文章主要介绍了Java 自旋锁的相关资料,帮助大家更好的理解和学习Java并发,感兴趣的朋友可以了解下
    2020-09-09
  • java.lang.NullPointerException出现的几种原因及解决方案

    java.lang.NullPointerException出现的几种原因及解决方案

    这篇文章主要介绍了java.lang.NullPointerException出现的几种原因及解决方案,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2020-05-05
  • java遍历读取整个redis数据库实例

    java遍历读取整个redis数据库实例

    这篇文章主要介绍了java遍历读取整个redis数据库实例,使用支持正则表达式的key搜索方法jedis.keys(“*”)实现,需要的朋友可以参考下
    2014-05-05
  • Spring Boot项目添加外部Jar包以及配置多数据源的完整步骤

    Spring Boot项目添加外部Jar包以及配置多数据源的完整步骤

    这篇文章主要给大家介绍了关于Spring Boot项目添加外部Jar包以及配置多数据源的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面来一起学习学习吧
    2020-06-06
  • java ExecutorService CompletionService线程池区别与选择

    java ExecutorService CompletionService线程池区别与选择

    这篇文章主要为大家介绍了java ExecutorService CompletionService线程池区别与选择使用示例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-09-09
  • java实现上传和下载工具类

    java实现上传和下载工具类

    这篇文章主要为大家详细介绍了java实现上传和下载工具类,文件上传到ftp服务工具类,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2017-05-05
  • 关于Java中常见的负载均衡算法

    关于Java中常见的负载均衡算法

    这篇文章主要介绍了关于Java中常见的负载均衡算法,负载平衡是一种电子计算机技术,用来在多个计算机、网络连接、CPU、磁盘驱动器或其他资源中分配负载,以达到优化资源使用、最大化吞吐率、最小化响应时间、同时避免过载的目的,需要的朋友可以参考下
    2023-08-08
  • 详解Spring-Boot中如何使用多线程处理任务

    详解Spring-Boot中如何使用多线程处理任务

    本篇文章主要介绍了详解Spring-Boot中如何使用多线程处理任务,具有一定的参考价值,感兴趣的小伙伴们可以参考一下。
    2017-03-03
  • Java 中的垃圾回收机制详解

    Java 中的垃圾回收机制详解

    这篇文章主要为大家详细介绍了Java垃圾回收机制的相关资料,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2021-09-09
  • SpringBoot使用编程方式配置DataSource的方法

    SpringBoot使用编程方式配置DataSource的方法

    这篇文章主要介绍了SpringBoot使用编程方式配置DataSource的方法,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2019-01-01

最新评论