Loading [MathJax]/jax/output/CommonHTML/config.js
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >Netty Recycler源码解读

Netty Recycler源码解读

作者头像
良辰美景TT
发布于 2018-12-26 08:13:02
发布于 2018-12-26 08:13:02
1.2K00
代码可运行
举报
运行总次数:0
代码可运行

Recycler是一个轻量级的对象缓存池,用来实现对象的复用。下面是使用Recycler的一个简单实例:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
import io.netty.util.Recycler;

public class RecycleTest {
    private static final Recycler<User> RECYCLER = new Recycler<User>() {
        //没有对象的时候,新建一个对象, 会传入一个handler,在Recycler池里,所有的对象都会转成DefaultHandle对象
        @Override
        protected User newObject(Handle<User> handle) {
            return new User(handle);
        }
    };

    private static class User {
        private final Recycler.Handle<User> handle;

        public User(Recycler.Handle<User> handle) {
            this.handle = handle;
        }

        public void recycle() {
            //通过handler进行对象的回收
            handle.recycle(this);
        }
    }

    public static void main(String[] args) {
        User user = RECYCLER.get();
        //直接调用user方法进行对象的回收
        user.recycle();

        User user1 = RECYCLER.get();
        //这里会返回true
        System.out.println(user1 == user);
    }
}
Recycler对象的创建

Recycler内部通过FastThreadLocal里的Stack栈来保存对象池,每次通过get方法从池中得到对象的时候,先通过FastThreadLocal得到Stack对象,具体的参数含义如下图所示:

Stack里通过数组存储着回收的对象,构造方法如下图:

Stack的构造方法

对象的回收

Recycler对象的回收会调用stack的push方法将对象放入到栈里,这样就完成了对象的回收,具体逻辑如下:

在push方法里,根据线程的不同,又可以分为同线程的回收,与异线程的回收。

同线程对象的回收

线程的回收相对比较简单,将对象放到Stack栈里就完成了对象的回收,代码如下:

判断对象是否回收的逻辑:

异线程对象的回收

异线程的回收是指创建对象的线程与调用recycler方法的线程不是同一个线程,这时候的回收逻辑就相对复杂了,里面用到了两个对象,分别为:

  • WeakOrderQueue 存储其它线程回收到本线程的对象,当某个线程从Stack中获取不到对象时会从WeakOrderQueue中获取对象。每个线程的Stack拥有1个WeakOrderQueue链表,链表每个节点对应1个其它线程的WeakOrderQueue,其它线程回收到该Stack的对象就存储在这个WeakOrderQueue里。
  • Link: WeakOrderQueue中包含1个Link链表,回收对象存储在链表某个Link节点里,当Link节点存储的回收对象满了时会新建1个Link放在Link链表尾,Link的容量为16。 对象结构如下图所示:

具体的回收过程可以分为:

  • 获取WeakOrderQueue
  • 如果没有相应的WeakOrderQueeu,则会创建WeakOrderQueue, 将创建线程的Stack与回收线程的WeakOrderQueue进行绑定,具体的代码如下:
  • 将对象追加到WeakOrderQueue
  • WeakOrderQueue的构造方法如下:
  • Link构造方法
获取一个对象

可以通过get方法从recycler对象里获取一个缓存的对象,下面是get方法的逻辑:

Recycler的get方法逻辑

Stack的pop方法

从其它线程获取对象放到stack里
  • 从其它线程获取对象入口
  • 从其它线程攻取对象
  • 将Link集合里的对象移到stack里,逻辑如下图:
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2018.12.12 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
Netty源码实战(十) - 性能优化
ThreadLocal最常用的两个接口是set和get 最常见的应用场景为在线程上下文之间传递信息,使得用户不受复杂代码逻辑的影响
JavaEdge
2022/11/30
5890
Netty源码实战(十) - 性能优化
Netty源码—9.性能优化和设计模式一
FastThreadLocal的作用与ThreadLocal相当,但比ThreadLocal更快。ThreadLocal的作用是多线程访问同一变量时能够通过线程本地化的方式避免多线程竞争、实现线程隔离。
东阳马生架构
2025/06/16
1050
面试官:说说Netty对象池的实现原理?
Netty 作为一个高性能的网络通讯框架,它内置了很多恰夺天工的设计,目的都是为了将网络通讯的性能做到极致,其中「对象池技术」也是实现这一目标的重要技术。
磊哥
2024/06/04
3340
Netty对象池
在平时工作中,听说和使用过连接池,线程池等.还有一种就是对象池,可以实现对象复用的功能. 当然实现对象池的方式手段有多种,比如有一个公共的池子,所有需要对象的线程通过并发控制的方式从池子中获取对象,并
书唐瑞
2022/06/02
6350
Netty对象池
Netty源码—9.性能优化和设计模式二
线程的Stack里有3指针:head、pre、cursor。往Stack中插入一个WeakOrderQueue都是往头部插入的(头插法)。head指向第一个WeakOrderQueue,cursor指向当前回收对象的WeakOrderQueue。
东阳马生架构
2025/06/16
630
7. SOFAJRaft源码分析—如何实现一个轻量级的对象池?
我在看SOFAJRaft的源码的时候看到了使用了对象池的技术,看了一下感觉要吃透的话还是要新开一篇文章来讲,内容也比较充实,大家也可以学到之后运用到实际的项目中去。
luozhiyun
2019/11/26
5650
可能有人听过ThreadLocal,但一定没人听过ThreadLocal对象池
JDK中的Thread大家肯定用过,只要是用过异步编程的同学肯定都熟悉。为了保存Thread中特有的变量,JDK引入了ThreadLocal类来专门对Thread的本地变量进行管理。
程序那些事
2022/05/25
4650
Netty 之 ChannelOutboundBuffer 源码分析
每个 ChannelSocket 的 Unsafe 都有一个绑定的 ChannelOutboundBuffer , Netty 向站外输出数据的过程统一通过 ChannelOutboundBuffer 类进行封装,目的是为了提高网络的吞吐量,在外面调用 write 的时候,数据并没有写到 Socket,而是写到了 ChannelOutboundBuffer 这里,当调用 flush 的时候,才真正的向 Socket 写出。
java404
2019/03/05
9940
【Netty】「源码解析」(二)HeapBuffer 创建过程详解:高效可靠的内存管理技巧
本篇博文是《从0到1学习 Netty》中源码系列的第二篇博文,主要内容是通过源码层层剖析 Netty 中 HeapBuffer 的创建过程,了解它是如何高效的对内存进行管理,往期系列文章请访问博主的 Netty 专栏,博文中的所有代码全部收集在博主的 GitHub 仓库中;
sidiot
2023/08/30
3770
【Netty】「源码解析」(二)HeapBuffer 创建过程详解:高效可靠的内存管理技巧
【Netty】ByteBuf (一)
所有的网路通信都涉及字节序列的移动,所以高效易用的数据结构明显是必不可少的。Netty的ByteBuf实现满足并超越了这些需求。
用户3467126
2019/07/03
7970
【Netty】ByteBuf (一)
【Netty】ByteBuf (二)
tiny:总共32个规格, 均是16的整数倍, 0B, 16B, 32B, 48B, 64B, 80B, 96B......496B small:4种规格, 512b, 1k, 2k, 4k nomal:3种规格, 8k, 16k, 32k
用户3467126
2019/07/03
4400
netty案例,netty4.1源码分析篇五《一行简单的writeAndFlush的都做了哪些事》
对于使用netty的小伙伴来说,ctx.writeAndFlush()再熟悉不过了,它可以将我们的消息发送出去。那么它都执行了那些行为呢,是怎么将消息发送出去的呢。
小傅哥
2020/07/14
7000
netty案例,netty4.1源码分析篇五《一行简单的writeAndFlush的都做了哪些事》
netty系列之:给ThreadLocal插上梦想的翅膀,详解FastThreadLocal
JDK中的ThreadLocal可以通过get方法来获得跟当前线程绑定的值。而这些值是存储在ThreadLocal.ThreadLocalMap中的。而在ThreadLocalMap中底层的数据存储是一个Entry数组中的。
程序那些事
2022/06/01
3940
Netty源码阅读入门实战(十)-性能优化1 性能优化工具类
ThreadLocal最常用的两个接口是set和get 最常见的应用场景为在线程上下文之间传递信息,使得用户不受复杂代码逻辑的影响
JavaEdge
2018/11/23
8520
Netty源码—7.ByteBuf原理三
PooledByteBufAllocator的directBuffer()方法通过其newDirectBuffer()方法执行代码directArena.allocate()时,首先会调用PoolArena的allocate()方法,然后会调用PoolArena的allocateNormal()方法,接着会调用PoolChunk的allocate()方法,并最终调用到PoolChunk的allocateSubpage()方法进行SubPage级别的内存分配。进行SubPage级别的内存分配时不会分配多个Page而只会分配一个Page的一部分。
东阳马生架构
2025/06/13
1210
Netty源码—8.编解码原理二
首先从tail结点开始往前传播。然后逐个调用ChannelHandler的write()方法,直到某个ChannelHandler不再往前传播write事件。接着逐个调用ChannelHandler的flush()方法,直到某个ChannelHandler不再往前传播flush事件。
东阳马生架构
2025/06/13
1140
Netty源码—6.ByteBuf原理一
答:ByteBuf可以按三个维度来进行分类:一个是堆内和堆外,一个是Unsafe和非Unsafe,一个是Pooled和非Pooled。
东阳马生架构
2025/06/10
1230
Netty 解码器抽象父类 ByteToMessageDecoder 源码解析
链接:https://www.jianshu.com/p/4c35541eec10
用户5224393
2019/08/13
1.4K0
Netty 解码器抽象父类 ByteToMessageDecoder 源码解析
netty源码分析之EventLoop中的线程FastThreadLocalThread和队列
它继承自SingleThreadEventLoop,它的超类是SingleThreadEventExecutor。而在下面你会发现NioEventLoopGroup中维护着多个SingleThreadEventExecutor。先来看下NioEventLoop和SingleThreadEventLoop、SingleThreadEventExecutor的代码。
山行AI
2020/04/07
1.3K1
netty源码分析之EventLoop中的线程FastThreadLocalThread和队列
Netty Review - ByteBuf内存池源码解析
ByteBuf 内存池是 Netty 中用于管理 ByteBuf 对象的一种机制,旨在提高内存的使用效率和性能。
小小工匠
2024/05/26
1570
Netty Review - ByteBuf内存池源码解析
相关推荐
Netty源码实战(十) - 性能优化
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验