常见面试题-Netty中ByteBuf类

了解 Netty 中的 ByteBuf 类吗?

答:

在 Java NIO 编程中,Java 提供了 ByteBuffer 作为字节缓冲区类型(缓冲区可以理解为一段内存区域),来表示一个连续的字节序列。

Netty 中并没有使用 Java 的 ByteBuffer,而是使用了新的缓冲类型 ByteBuf,特性如下:

  • 允许自定义缓冲类型

  • 复合缓冲类型中内置的透明的零拷贝实现

  • 开箱即用的动态缓冲类型,具有像 StringBuffer 一样的动态缓冲能力

  • 不再需要调用 flip() 方法

    Java 的 ByteBuffer 类中,需要使用 flip() 来进行读写两种模式的切换

  • 正常情况下具有比 ByteBuffer 更快的响应速度

Java 中的 ByteBuffer:

主要需要注意有 3 个属性:position、limit、capacity

  • capacity:当前数组的容量大小
  • position:写入模式的可写入数据的下标,读取模式的可读取数据下标
  • limit:写入模式的可写入数组大小,读取模式的最多可以读取数据的下标

假如说数组容量是 10,那么三个值初始值为:

position = 0
limit = 10
capacity = 10

假如写入 4 个字节的数据,此时三个值如下:

position = 4
limit = 10
capacity = 10

如果切换到读取数据模式(使用 flip()),会改变上边的三个值,会从 position 的位置开始读取数据到 limit 的位置

position = 0
limit = 4
capacity = 10

Netty 中的 ByteBuf:

ByteBuf 主要使用两个指针来完成缓冲区的读写操作,分别是: readIndexwriteIndex

  • 当写入数据时,writeIndex 会增加
  • 当读取数据时,readIndex 会增加,但不会超过 writeIndex

ByteBuf 的使用:

public static void main(String[] args) {ByteBuf buffer = Unpooled.buffer(10);System.out.println("----------初始化ByteBuf----------");printByteBuffer(buffer);System.out.println("----------ByteBuf写入数据----------");String str = "hello world!";buffer.writeBytes(str.getBytes());printByteBuffer(buffer);System.out.println("----------ByteBuf读取数据----------");while (buffer.isReadable()) {System.out.print((char)buffer.readByte());}System.out.println();printByteBuffer(buffer);System.out.println("----------ByteBuf释放无用空间----------");buffer.discardReadBytes();printByteBuffer(buffer);System.out.println("----------ByteBuf清空----------");buffer.clear();printByteBuffer(buffer);
}
private static void printByteBuffer(ByteBuf buffer) {System.out.println("readerIndex:" + buffer.readerIndex());System.out.println("writerIndex:" + buffer.writerIndex());System.out.println("capacity:" + buffer.capacity());
}
/**输出**/
----------初始化ByteBuf----------
readerIndex:0
writerIndex:0
capacity:10
----------ByteBuf写入数据----------
readerIndex:0
writerIndex:12
capacity:64
----------ByteBuf读取数据----------
hello world!
readerIndex:12
writerIndex:12
capacity:64
----------ByteBuf释放无用空间----------
readerIndex:0
writerIndex:0
capacity:64
----------ByteBuf清空----------
readerIndex:0
writerIndex:0
capacity:64

ByteBuf 的 3 种使用模式:

ByteBuf 共有 3 种使用模式:

  • 堆缓冲区模式(Heap Buffer)

    堆缓冲区模式又称为 “支撑数据”,其数据存放在 JVM 的堆空间

    优点:

    • 数据在 JVM 堆中存储,可以快速创建和释放,并且提供了数组直接快速访问的方法

    缺点:

    • 每次数据与 IO 进行传输时,都需要将数据复制到直接缓冲区(这里为什么要将数据复制到直接缓冲区的原因在上边的 直接内存比堆内存快在了哪里? 问题中已经讲过)

    创建代码:

    ByteBuf buffer = Unpooled.buffer(10);
    
  • 直接缓冲区模式(Direct Buffer)

    直接缓冲区模式属于堆外分配的直接内存,不占用堆的容量

    优点:

    • 使用 socket 传输数据时性能很好,避免了数据从 JVM 堆内存复制到直接缓冲区

    缺点:

    • 相比于堆缓冲区,直接缓冲区分配内存空间和释放更为昂贵

    创建代码:

    ByteBuf buffer = Unpooled.directBuffer(10);
    
  • 复合缓冲区模式(Composite Buffer)

    本质上类似于提供一个或多个 ByteBuf 的组合视图

    优点:

    • 提供一种方式让使用者自由组合多个 ByteBuf,避免了复制和分配新的缓冲区

    缺点:

    • 不支持访问其支撑数据,如果要访问,需要先将内容复制到堆内存,再进行访问

    创建代码:

    public static void main(String[] args) {
    //        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(Test.class);// 创建一个堆缓冲区ByteBuf heapBuf = Unpooled.buffer(2);String str1 = "hi";heapBuf.writeBytes(str1.getBytes());// 创建一个直接缓冲区ByteBuf directBuf = Unpooled.directBuffer(5);String str2 = "nihao";directBuf.writeBytes(str2.getBytes());// 创建一个复合缓冲区CompositeByteBuf compositeByteBuf = Unpooled.compositeBuffer(10);compositeByteBuf.addComponents(heapBuf, directBuf);// 检查是否支持支撑数组,发现并不支持if (!compositeByteBuf.hasArray()) {for (ByteBuf buf : compositeByteBuf) {// 第一个字节偏移量int offset = buf.readerIndex();// 总共数据长度int length = buf.readableBytes();byte[] bytes = new byte[length];// 不支持访问支撑数组,需要将内容复制到堆内存中,即 bytes 数组中,才可以进行访问buf.getBytes(offset, bytes);printByteBuffer(bytes, offset, length);}}
    }private static void printByteBuffer(byte[] array, int offset, int length) {System.out.println("array:" + array);System.out.println("array->String:" + new String(array));System.out.println("offset:" + offset);System.out.println("len:" + length);
    }
    /**输出**/
    array:[B@4f8e5cde
    array->String:hi
    offset:0
    len:2
    array:[B@504bae78
    array->String:nihao
    offset:0
    len:5
    

Netty 中 ByteBuf 如何分配?有池化的操作吗?

答:

ByteBuf 的分配接口定义在了 ByteBufAllocator 中,他的直接抽象类是 AbstractByteBufAllocator,而 AbstractByteBufAllocator 有两种实现:PooledByteBufAllocatorUnpooledByteBufAllocator

在这里插入图片描述

  • PooledByteBufAllocator 提供了池化的操作,将 ByteBuf 实例放入池中,提升了性能,将内存碎片化减到了最小UnpooledByteBufAllocator。(这个实现采用了一种内存分配的高效策略,成为 jemalloc,已经被好几种现代操作系统所采用)
  • UnpooledByteBufAllocator 在每次创建缓冲区时,都会返回一个新的 ByteBuf 实例,这些实例由 JVM 负责 gc 回收

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/178214.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

MySQL主从同步延迟原因与解决方案

一、MySQL数据库主从同步延迟产生的原因 MySQL的主从复制都是单线程的操作,主库对所有DDL和DML产生的日志写进binlog,由于binlog是顺序写,所以效率很高。 Slave的SQL Thread线程将主库的DDL和DML操作事件在slave中重放。DML和DDL的IO操作…

08 木谷博客系统RBAC权限设计

这节内容说一下木谷博客系统的权限设计,采用现在主流的权限模型RBAC,对应关系如下: 以上5张表都在mugu_auth_server这个库中 该部分的服务单独定义在user-boot这个模块中。 将角色、权限对应关系加载到Redis 木谷博客系统在认证中心颁发令牌的时候是将用户的角色保存到令牌…

MySQL用得好好的,为何要转ES?

MySQL是一种关系型数据库,它可以高效地存储和查询结构化的数据。 ES是一种分布式搜索引擎,它可以快速地对海量的非结构化或半结构化的数据进行全文检索和分析。 MySQL 和 ES 的数据存储方式也不同。MySQL 中的数据通常是以关系型表的形式存储在磁盘上&…

EOCR-PFZ数码型产品与控制柜主回路的连接方式

上海韩施电气自动化设备有限公司 施耐德EOCR新一代数码型电动机保护器具有体积小、精度高、抗干扰能力强等特点。为方便安装,EOCR数码型产品与控制柜主回路的连接具有多种方式,分别是:窗口型、贯穿性和端子型。 窗口型(韩施电气…

vue3中shallowReactive与shallowRef

shallowReactive与shallowRef shallowReactive: 只处理了对象内最外层属性的响应式(也就是浅响应式) shallowRef: 只处理了value的响应式, 不进行对象的reactive处理 总结: reactive与ref实现的是深度响应式, 而shallowReactive与shallowRef是浅响应式。 什么时候用浅响应…

万字解析设计模式之观察者模式、中介者模式、访问者模式

一、观察者模式 1.1概述 观察者模式是一种行为型设计模式,它允许一个对象(称为主题或可观察者)在其状态发生改变时,通知它的所有依赖对象(称为观察者)并自动更新它们。这种模式提供了一种松耦合的方式&…

园区智能配电系统(电力智能监控系统)

园区智能配电系统是一种针对园区电力配送和管理的智能化系统。它的主要功能是实时监控设备运行情况,进行电能质量分析,监控电能损耗,以及分时段用电统计等。 具体来说,园区智能配电系统可以利用现代技术如RS-485总线通信、数据库管…

Android Studio 添加so无法打包进apk问题

1.开发环境: Android Studio 2022.3.1 Patch 2 jdk 17 gradle-7.4 2.build.grade配置检查 首先查看build.gradle中是否设置sourceSets ,如果设置的话,打包的时候so是被指导libs目录下的,所有就不能把jnilibs下。 sourceSets {mai…

计算机视觉面试题-03

1、简单介绍一下sigmoid,relu,softplus,tanh,RBF及其应用场景 这里简单介绍几个激活函数及其应用场景: Sigmoid 函数(Logistic 函数): 公式: s i g m a ( x ) 1 1 e …

2023仿聚合搜索程序源码/轻量级搜狗泛站群程序源码/PHP整站源码+完美SEO优化+符合搜狗算法

源码简介: 2023仿聚合搜索/轻量级搜狗泛站群程序整站源码,作为PHP源码,可以完美SEO优化,符合搜狗搜索引擎算法。 轻量级的PHP搜狗泛站群程序源码,完美SEO优化符合搜狗搜索引擎算法,无需任何采集&#xff…

【Unity细节】为什么加载精灵图集直接导致Unity引擎崩溃

👨‍💻个人主页:元宇宙-秩沅 hallo 欢迎 点赞👍 收藏⭐ 留言📝 加关注✅! 本文由 秩沅 原创 😶‍🌫️收录于专栏:unity细节和bug 😶‍🌫️优质专栏 ⭐【…

Oracle Linux 9.3 发布

导读Oracle Linux 9 系列发布了第 3 个版本更新,支持 64 位 Intel 和 AMD (x86_64) 以及 64 位 Arm (aarch64) 平台。与所有的 Oracle Linux 版本一样,此版本与相应 RHEL 版本 100% 应用二进制兼容。 对于 x86_64 和 aarch64 架构,Oracle Li…

Unity - Graphic解析

Gpahic 的作用 Graphic 是 Unity最基础的图形基类。主要负责UGUI的显示部分。 由上图可以看你出我们经常使用的Image,Text,都是继承自Graphic。 Graphic的渲染流程 在Graphic的源码中有以下属性 [NonSerialized] private CanvasRenderer m_CanvasRend…

Kafka生产者发送消息的流程

Kafka 生产者发送消息的流程涉及多个步骤,从消息的创建到成功存储在 Kafka 集群中。以下是 Kafka 生产者发送消息的主要步骤: 1. 创建消息 生产者首先创建一个消息,消息通常包含一个键(可选)和一个值,以及…

Verilog基础:时序调度中的竞争(二)

相关阅读 Verilog基础https://blog.csdn.net/weixin_45791458/category_12263729.html?spm1001.2014.3001.5482 作为一个硬件描述语言,Verilog HDL常常需要使用语句描述并行执行的电路,但其实在仿真器的底层,这些并行执行的语句是有先后顺序…

Ubuntu:安装VSCode

参考博客Ubuntu下安装VSCODE_ubuntu安装vscode-CSDN博客中的第二种方式【安装包方式安装】,即可,安装非常easy~~~ 安装包方式安装: 1. 从VSCode官网下载最新版的deb安装包: https://code.visualstudio.com/Download,…

使用Prometheus监控Synology(群辉)

1、简介 在现代的IT环境中,对于服务器和网络设备的监控是至关重要的。Synology(群辉)作为一种流行的网络存储解决方案,为用户提供了高性能和可靠的存储服务。然而,了解Synology设备的运行状况和性能指标对于确保其正常…

车辆管控大数据可视化平台案例源码分析【可视化项目案例-10】

🎉🎊🎉 你的技术旅程将在这里启航! 🚀🚀 本专栏包括但不限于大屏可视化、图表可视化等等。订阅专栏用户在文章底部可下载对应案例源码以供大家深入的学习研究。 🎓 每一个案例都会提供完整代码和详细的讲解,不论你是初学者还是资深开发者,这里都有适合你的内容。…

Windows平台下的oracle 11G-11.2.0.4补丁升级操作指南

序号 文件名称 文件说明 1 p6880880_112000_MSWIN-x86-64_OPatch 11.2.0.3.33 for DB 11.2.0.0.0 (Feb 2022) 用于升级 OPatch 2 DB_PSU_11.2.0.4.220118 (Jan 2022)_p33488457_112040_MSWIN-x86-64 主要补丁文件 注意:请用管理员权限运行文件内命令&#…

Stable Video Diffusion(SVD)安装和测试

Stable Video Diffusion(SVD)安装和测试 官网 github | https://github.com/Stability-AI/generative-modelsHugging Face | https://huggingface.co/stabilityai/stable-video-diffusion-img2vid-xtPaper | https://stability.ai/research/stable-vid…