Nettyの前置理论篇

本篇主要介绍NIO中的三大组件:Channel、Buffer、Selector的理论知识

1、NIO基本概念

        NIO(non-blocking io 或 new io)区别于传统IO,是一种面向缓冲区的非阻塞IO操作,在传统IO中,数据是以字节或字符为单位从流中顺序读写,并且所有的读写操作都是阻塞的。例如,当一个线程调用read()方法时,该线程会被阻塞,直到数据被读入或发生错误。

        NIO相比于传统的IO有以下的特点和优势:

  • 非阻塞IO: NIO允许通道在非阻塞模式下工作,这意味着一个线程可以发起IO操作而不必等待操作完成,从而使得同一个线程可以同时处理多个IO操作。

  • 面向缓冲区: NIO通过缓冲区进行数据的读写操作,而不是直接操作流。这种方式更接近底层操作系统的IO模型,能够提高效率。

  • 多路复用: 通过选择器,一个线程可以监控多个通道的IO事件,如连接请求、读写数据等。这种机制使得NIO非常适合于实现高性能的服务器和网络应用。

        NIO又包含了三大组件:

        缓冲区(Buffer)

        缓冲区是一个容器对象,用于包含特定基本类型的数据。所有的数据都通过缓冲区进行读写操作。常见的缓冲区类型包括:

  • ByteBuffer:字节缓冲区
  • CharBuffer:字符缓冲区
  • IntBuffer、LongBuffer、FloatBuffer、DoubleBuffer:对应于其他基本数据类型的缓冲区

        缓冲区的核心属性包括:

  • Capacity:缓冲区能容纳的数据元素的总数
  • Position:下一个要读取或写入的元素的位置
  • Limit:写入/读取限制
  • Mark:一个备忘位置,通过reset()方法可以恢复到这个位置

        通道(Channel)

        通道类似于传统IO中的流(Stream),但不同的是,通道可以进行双向操作(既可以读也可以写)。通道用于从数据源(如文件、网络套接字)读数据或将数据写入到数据源。

  • 通道可以进行异步读写
  • 通道可以与缓冲区直接交互
  • 通道可以映射到文件、网络套接字等

        常见的通道类型包括:

  • FileChannel:用于文件的通道
  • SocketChannel:用于TCP连接的通道
  • ServerSocketChannel:用于监听TCP连接的通道
  • DatagramChannel:用于UDP连接的通道

        选择器(Selector)

        选择器是Java NIO的核心组件之一,用于管理多个通道的IO事件。通过选择器,一个线程可以处理多个通道的读写事件,从而实现高效的多路复用,如果使用传统的IO:

        假设每个socket连接都要通过新创建一个线程去处理,第一随着连接数的增加,线程的数量势必也会不断增加,第二,如果线程数量大于cpu核心数,会频繁发生上下文切换问题,很影响性能。

        如果采用线程池的方式改进,一个线程可以服务多个socket连接,但是如果在阻塞模式下,线程依旧仅能处理一个 socket 连接。例如一个餐馆服务员面对A,B两个客人,A一直在看菜单,服务员无法利用这段时间去兼顾B。                

2、传统IO面向流和NIO面向缓冲区的区别

        首先面向流是一种逐个字节或字符处理的思想:

        数据是按顺序一个字节一个字节地读取或写入的,像流水一样。处理时不关心数据的整体,只关注当前读取或写入的字节。

        并且读写操作是阻塞的,一个读写操作没有完成,当前线程会一直等待。例如,当你从一个输入流中读取数据时,线程会被阻塞,直到数据被完全读取。

        而面向缓冲区是一种数据块处理的思想:

        数据通过缓冲区(Buffer)批量读取或写入。缓冲区是内存中的一个块,数据在缓冲区中处理,然后通过通道(Channel)整体读入或写出。

        通道可以配置为非阻塞模式,允许线程在数据还未准备好时继续执行其他操作。例如,使用选择器(Selector)来管理多个通道,一个线程可以处理多个连接。

3、通道(Channel)和缓冲区(Buffer)的联系

        缓冲区在读写操作过程中会维护三个关键属性:position(指针)、limit(限制)和capacity(容量)。        

  • position:指示下一个要读取或写入的元素位置。
  • limit:在读模式下,limit表示缓冲区可读数据的大小;在写模式下,limit表示缓冲区总的容量。
  • capacity:缓冲区的总大小,在缓冲区创建时设定,不可改变。(不同于集合,没有扩容机制)

        在获取缓冲区实例时,通常需要指定容量,假设我们指定的容量是10:

        然后向缓冲区放入了4个字节的数据:

        通过filp方法切换至读取模式,此时position指针代表的是当前从索引为几的地方开始读,limit也变成了可以最多读取多少个元素。

        在读取了4个字节后:

        最后调用clear方法切换回写入模式:(clear会清除所有元素)

        compact方法是将未读完的元素向前压缩,然后切换至写模式

        那么数据是如何在通道和缓冲区之间进行读写操作的呢?

        读操作:当从通道读取数据时,数据被读入到缓冲区中。

  1. 调用通道的read方法,将数据从通道读取到缓冲区。
  2. 使用缓冲区的filp方法切换到读取模式。
  3. 从缓冲区中读取数据。

        写操作:当向通道写入数据时,数据从缓冲区写入到通道中。

  1. 将数据放入缓冲区。
  2. 使用缓冲区的clear() 或 compact() 方法切换到写入模式。
  3. 调用通道的write方法,将数据从缓冲区写入到通道。

        总结:

  • 通道是数据传输的载体,负责从数据源读取数据或将数据写入数据源。
  • 缓冲区是数据的临时存储区,用于存放从通道中读入的数据或将要写入通道的数据。

4、选择器(Selector)是如何实现多路复用

        在学习选择器(Selector)是如何实现多路复用前,首先需要了解一下什么是多路复用:

        使用一个单独的线程同时处理多个I/O操作,而不需要为每个I/O流创建单独的线程或进程,其关键点在于,通过在一个线程中管理多个连接,避免线程创建和上下文切换的开销,并且系统监视多个I/O流,当某个流就绪时(如有数据可读、可以写入等),会通知应用程序处理这个流上的I/O事件。同时/O操作不会阻塞进程或线程,可以同时处理多个I/O请求。

        选择器(Selector)实现多路复用,一般需要分为以下几步:

  1. 将通道(Channel)配置为非阻塞模式,然后注册到选择器上,注册时需要指定需要被监视的事件类型,如连接事件、读事件、写事件。
  2. 选择器通过select()方法轮询已注册通道的I/O事件。select()方法会阻塞,直到至少有一个通道准备好进行I/O操作(如有数据可读)。一旦有通道就绪,选择器返回已就绪通道的集合,这些通道可以进行I/O操作。
  3. 程序通过迭代已就绪通道的集合,逐个处理每个通道的I/O事件。
  4. 根据通道的事件类型(如读就绪、写就绪),执行相应的I/O操作。

        在第一步中,所有通道都被配置为非阻塞模式,这意味着I/O操作不会阻塞线程。如果通道当前没有数据可读或不能写入,操作会立即返回而不会阻塞

        在第二步中,选择器使用事件通知机制,监视所有注册通道的状态。当一个或多个通道的状态发生变化(如有数据可读),选择器会通知应用程序。

什么是事件通知机制?

简单来说,每个注册通道在选择器中都有一个对应的键(SelectionKey),键中记录了通道和事件类型,选择器内部维护一个键集合(Key Set),包含所有注册通道的键和事件类型,选择器在轮询时更新键集合,将就绪通道的键放入已就绪键集合(Ready Key Set)。这样选择器在每次轮询时,只处理已就绪通道的I/O事件,未就绪通道不做处理。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

java基础语法整理 ----- 上

java基础语法 一、变量二、数据类型三、标识符四、键盘录入五、判断语句1. 三种格式2. 练习题 六、switch语句七、循环八、循环控制语句九、方法 一、变量 1.什么是变量: 在程序运行过程中,其值可以发生改变的量从本质上讲,变量是内存中的一…

使用树莓派和 L298N 来 DIY 小车底盘

树莓派小车可以作为 STEM(科学、技术、工程、数学)教育的工具,在实际操作中帮助学生理解和学习电子技术、编程和机器人原理。可以培养学生的动手能力、解决问题的能力和创新思维。 随着近年 AI 技术的高速发展,SLAM、VSLAM 甚至带…

JDBC学习笔记(三)高级篇

一、JDBC 优化及工具类封装 1.1 现有问题 1.2 JDBC 工具类封装 V1.0 resources/db.properties配置文件: driverClassNamecom.mysql.cj.jdbc.Driver urljdbc:mysql:///atguigu usernameroot password123456 initialSize10 maxActive20 工具类代码: p…

PDF编辑与转换的终极工具智能PDF处理Acrobat Pro DC

Acrobat Pro DC 2023是一款功能全面的PDF编辑管理软件,支持创建、编辑、转换、签署和共享PDF文件。它具备OCR技术,可将扫描文档转换为可编辑文本,同时提供智能PDF处理技术,确保文件完整性和可读性。此外,软件还支持电子…

【远程连接服务器】—— Workbench和Xshell远程连接阿里云服务器失败和运行Xshell报错找不到 MSVCP110.d的问题分析及解决

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 前言一、远程连接不上服务器1. Workbench远程连接失败2.Xshell也连接不上3.解决方法(1)问题描述:(2)解决: 4.再次连接服务器 二、运行Xshell…

Python中猴子补丁是什么,如何使用

1、猴子补丁奇遇记 🐒 在Python的世界深处,隐藏着一种神秘而又强大的技巧——猴子补丁(Monkey Patching)。这是一项允许你在程序运行时动态修改对象(如模块、类或函数)的行为的技术。它得名于其“快速修补…

Segment Anything

参考:【图像分割】Segment Anything(Meta AI)论文解读-CSDN博客 背景 提示分割任务:在给定任何分割提示下返回一个有效的分割掩码目标:开发一个可提示的图像分割的基础模型,在一个广泛的数据集上预训练&a…

后端启动项目端口冲突问题解决

后端启动项目端口冲突 原因: Vindows Hyper-V虚拟化平台占用了端口。 解决方案一: 查看被占用的端口范围,然后选择一个没被占用的端口启动项目。netsh interface ipv4 show excludedportrange protocoltcp 解决方案二: 禁用H…

解决Android Studio Iguana版本不显示原创的GradleTask问题

问题描述: 下面是我的AndroidStudio版本号,升级后我发现项目里面自定义的gradletask找不到了??? 解决方案: 1、去setting里面把下面红框里面的选项勾选一下,缺点就是sync的时候会慢一些。 2、…

elasticsearch安装与使用(4)-搜索入门

1、创建索引 PUT /hotel {"mappings": {"properties":{"title":{"type": "text"},"city":{"type": "keyword"},"price":{"type":"double"}}} }2、写入文档 …

手把手教你实现条纹结构光三维重建(1)——多频条纹生成

关于条纹结构光三维重建的多频相移、格雷码、格雷码相移、互补格雷码等等编码方法,我们在大多数平台上,包括现在使用语言大模型提问,都可以搜到相关的理论,本人重点是想教会你怎么快速用代码实现。 首先说下硬件要求,…

手搓文件格式转换

最初目标: 自己搞一个免费的pdf文件转换 根据现有的开源jar 项目实现思路: 1. 项目原因a. 我想转换文件b. wps 文件转换 2. 最初的状态a. jar运行的b. main,输入文件路径c. 一定的编程能力的人才能得 3. 开始构思项目a. 网页版本b. 想着大家一起用 4. …

vue的ant design多个输入框,输入其中一个输入框自动触发下一个输入框的校验

vue多个输入框,各输入值之间相互影响。 需求描述: 表单含有3个输入框 1)额定电压:必填项,数值,手动录入,最大录入40字,默认单位为V,保留1为小数 2)最大电压…

10倍速开发开关电源:PSIM DLL集成指南与如何单步调试你的代码

文末有彩蛋哦。 去年提到要写一篇如何在利用PSIM Visual Studio进行仿真联调,加速实际嵌入式端C代码的开发,但因为懒一直没兑现。 本期简单总结下实现的方法。 特别声明:本文约一半以上内容有kimi/文心一言提问式生成,仅用于技…

mysql表级锁(表锁/元数据锁/意向锁)

文章目录 表级锁的分类1、表锁(分类)1.表共享读锁(read lock)2.表独占写锁(write lock)3.语法: 2、元数据锁(meta data lock )3、意向锁1.意向共享锁(IS):由语…

最小相位系统

最小相位系统 1、传递函数 一个线性系统的响应。 比如一个RC低通滤波器: 交流分量在电容的充放电中被滤除掉,通过设置电容器的电容值,以及电阻值,能够控制这种滤除能力,这个参数为RC。 电容的电抗为 1 / j w C 1/j…

【el-tooltips改造】Vue实现文本溢出才显示el-tooltip,否则不显示el-tooltips

实现原理: 使用disabled属性控制el-tooltip的content显示与隐藏; 目标: 1行省略、多行省略、可缩放页面内的文本省略都有效。 实现方式: 1、自定义全局指令,tooltipAutoShow.js代码如下(参考的el-table中的…

TH方程学习 (7)

一、内容介绍 TH存在广泛应用,在下面案例中,将介绍几种相对运动模型,斜滑接近模型,本节学习斜滑接近制导方法能够对接近时间、接近方向以及自主接近过程的相对速度进行控制。施加脉冲时刻追踪器的位置连线可构成一条直线&#xf…

http接口上传文件响应413:413 Request Entity Too Large

目录 一、场景简介二、异常展示三、原因四、解决 一、场景简介 1、服务端有经过nginx代理 2、上传文件超过5M时,响应码为413 3、上传文件小于5M时,上传正常 二、异常展示 三、原因 nginx限制了上传数据的大小 四、解决 扩大nginx上传数据的大小 步…

QT4-QT5升级(3)GBK-UTF-8-乱码“常量中有换行符”

乱码有两种:我命名为汉字乱码菱形乱码如下: 1.文件编码为: GB2312 打开编码: GB2312 编译后: QString 部分字符串 常量中有换行符 char * …