面试官:什么是NIO?NIO的原理是什么机制?

最通俗易懂的NIO讲解 一、NIO是什么?NIO的全称是New I/O,与之相对应的是Java中传统的I/O,这里都指的是Java的API包。传统的IO包提供的是同步阻塞IO,即当用户线程发出IO请求后,内核会去查看数据是否已经就绪,若未就绪,则用户线程会处于阻塞状态(让出CPU),当数据就绪后,内核会将数据复制到用户线程,并把结果返回给用户线程,同时接触用户线程的阻塞,同步体现在用户线程需要等待数据就绪后才能向后执行(... 阅读详情

 推荐阅读:2020年最新的常问企业面试题大全以及答案

来源:https://blog.youkuaiyun.com/qq_36520235/


NIO和IO到底有什么区别?有什么关系?

首先说一下核心区别:

  1. NIO是以块的方式处理数据,但是IO是以最基础的字节流的形式去写入和读出的。所以在效率上的话,肯定是NIO效率比IO效率会高出很多。

  2. NIO不在是和IO一样用OutputStream和InputStream 输入流的形式来进行处理数据的,但是又是基于这种流的形式,而是采用了通道和缓冲区的形式来进行处理数据的。

  3. 还有一点就是NIO的通道是可以双向的,但是IO中的流只能是单向的。

  4. 还有就是NIO的缓冲区(其实也就是一个字节数组)还可以进行分片,可以建立只读缓冲区、直接缓冲区和间接缓冲区,只读缓冲区很明显就是字面意思,直接缓冲区是为加快 I/O 速度,而以一种特殊的方式分配其内存的缓冲区。

  5. 补充一点:NIO比传统的BIO核心区别就是,NIO采用的是多路复用的IO模型,普通的IO用的是阻塞的IO模型,两个之间的效率肯定是多路复用效率更高

先了解一下什么是通道,什么是缓冲区的概念

通道是个什么意思?

  • 通道是对原 I/O 包中的流的模拟。到任何目的地(或来自任何地方)的所有数据都必须通过一个 Channel 对象(通道)。一个 Buffer 实质上是一个容器对象。发送给一个通道的所有对象都必须首先放到缓冲区中;同样地,从通道中读取的任何数据都要读到缓冲区中。Channel是一个对象,可以通过它读取和写入数据。拿 NIO 与原来的 I/O 做个比较,通道就像是流。

  • 正如前面提到的,所有数据都通过 Buffer 对象来处理。您永远不会将字节直接写入通道中,相反,您是将数据写入包含一个或者多个字节的缓冲区。同样,您不会直接从通道中读取字节,而是将数据从通道读入缓冲区,再从缓冲区获取这个字节。

缓冲区是什么意思:

  • Buffer 是一个对象, 它包含一些要写入或者刚读出的数据。在 NIO 中加入 Buffer 对象,体现了新库与原 I/O 的一个重要区别。在面向流的 I/O 中,您将数据直接写入或者将数据直接读到 Stream 对象中

  • 在 NIO 库中,所有数据都是用缓冲区处理的。在读取数据时,它是直接读到缓冲区中的。在写入数据时,它是写入到缓冲区中的。任何时候访问 NIO 中的数据,您都是将它放到缓冲区中。

  • 缓冲区实质上是一个数组。通常它是一个字节数组,但是也可以使用其他种类的数组。但是一个缓冲区不 仅仅 是一个数组。缓冲区提供了对数据的结构化访问,而且还可以跟踪系统的读/写进程

缓冲区的类型:

ByteBuffer
CharBuffer
ShortBuffer
IntBuffer
LongBuffer
FloatBuffer
DoubleBuffer

NIO的底层工作原理

先来了解一下buffer的工作机制:

  • capacity 缓冲区数组的总长度

  • position 下一个要操作的数据元素的位置

  • limit 缓冲区数组中不可操作的下一个元素的位置,limit<=capacity

  • mark 用于记录当前 position 的前一个位置或者默认是 0

1.这一步其实是当我们刚开始初始化这个buffer数组的时候,开始默认是这样的

2、但是当你往buffer数组中开始写入的时候几个字节的时候就会变成下面的图,position会移动你数据的结束的下一个位置,这个时候你需要把buffer中的数据写到channel管道中,所以此时我们就需要用这个buffer.flip();方法,

3、当你调用完2中的方法时,这个时候就会变成下面的图了,这样的话其实就可以知道你刚刚写到buffer中的数据是在position---->limit之间,然后下一步调用clear();

4、这时底层操作系统就可以从缓冲区中正确读取这 5 个字节数据发送出去了。在下一次写数据之前我们在调一下 clear() 方法。缓冲区的索引状态又回到初始位置。(其实这一步有点像IO中的把转运字节数组 char[] buf = new char[1024]; 不足1024字节的部分给强制刷新出去的意思)

补充:

1、这里还要说明一下 mark,当我们调用 mark() 时,它将记录当前 position 的前一个位置,当我们调用 reset 时,position 将恢复 mark 记录下来的值

2.clear()方法会:清空整个缓冲区。position将被设回0,limit被设置成 capacity的值(这个个人的理解就是当你在flip()方法的基础上已经记住你写入了多少字节数据,直接把position到limit之间的也就是你写入已经记住的数据给“复制”到管道中)

3.当你把缓冲区的数局写入到管道中的时候,你需要调用flip()方法将Buffer从写模式切换到读模式,调用flip()方法会将position设回0,并将limit设置成之前position的值。buf.flip();(其实我个人理解的就相当于先记住缓冲区缓冲了多少数据)

NIO 工作代码示例

public void selector() throws IOException {
//先给缓冲区申请内存空间
        ByteBuffer buffer = ByteBuffer.allocate(1024);
     //打开Selector为了它可以轮询每个 Channel 的状态
        Selector selector = Selector.open();
        ServerSocketChannel ssc = ServerSocketChannel.open();
        ssc.configureBlocking(false);//设置为非阻塞方式
        ssc.socket().bind(new InetSocketAddress(8080));
        ssc.register(selector, SelectionKey.OP_ACCEPT);//注册监听的事件
        while (true) {
            Set selectedKeys = selector.selectedKeys();//取得所有key集合
            Iterator it = selectedKeys.iterator();
            while (it.hasNext()) {
                SelectionKey key = (SelectionKey) it.next();
                if ((key.readyOps() & SelectionKey.OP_ACCEPT) == SelectionKey.OP_ACCEPT) {
                    ServerSocketChannel ssChannel = (ServerSocketChannel) key.channel();
                 SocketChannel sc = ssChannel.accept();//接受到服务端的请求
                    sc.configureBlocking(false);
                    sc.register(selector, SelectionKey.OP_READ);
                    it.remove();
                } else if 
                ((key.readyOps() & SelectionKey.OP_READ) == SelectionKey.OP_READ) {
                    SocketChannel sc = (SocketChannel) key.channel();
                    while (true) {
                        buffer.clear();
                        int n = sc.read(buffer);//读取数据
                        if (n <= 0) {
                            break;
                        }
                        buffer.flip();
                    }
                    it.remove();
                }
            }
        }
}

最后给大家看一下整体的NIO的示意图

NIO和Netty的工作模型对比?

(1)NIO的工作流程步骤:

  1. 首先是先创建ServerSocketChannel 对象,和真正处理业务的线程池

  2. 然后给刚刚创建的ServerSocketChannel 对象进行绑定一个对应的端口,然后设置为非阻塞

  3. 然后创建Selector对象并打开,然后把这Selector对象注册到ServerSocketChannel 中,并设置好监听的事件,监听 SelectionKey.OP_ACCEPT

  4. 接着就是Selector对象进行死循环监听每一个Channel通道的事件,循环执行 Selector.select() 方法,轮询就绪的 Channel

  5. 从Selector中获取所有的SelectorKey(这个就可以看成是不同的事件),如果SelectorKey是处于 OP_ACCEPT 状态,说明是新的客户端接入,调用 ServerSocketChannel.accept 接收新的客户端。

  6. 然后对这个把这个接受的新客户端的Channel通道注册到ServerSocketChannel上,并且把之前的OP_ACCEPT 状态改为SelectionKey.OP_READ读取事件状态,并且设置为非阻塞的,然后把当前的这个SelectorKey给移除掉,说明这个事件完成了

  7. 如果第5步的时候过来的事件不是OP_ACCEPT 状态,那就是OP_READ读取数据的事件状态,然后调用本文章的上面的那个读取数据的机制就可以了

(2)Netty的工作流程步骤:

  1. 创建 NIO 线程组 EventLoopGroup 和 ServerBootstrap。

  2. 设置 ServerBootstrap 的属性:线程组、SO_BACKLOG 选项,设置 NioServerSocketChannel 为 Channel,设置业务处理 Handler

  3. 绑定端口,启动服务器程序。

  4. 在业务处理 TimeServerHandler 中,读取客户端发送的数据,并给出响应

(3)两者之间的区别:

  1. OP_ACCEPT 的处理被简化,因为对于 accept 操作的处理在不同业务上都是一致的。

  2. 在 NIO 中需要自己构建 ByteBuffer 从 Channel 中读取数据,而 Netty 中数据是直接读取完成存放在 ByteBuf 中的。相当于省略了用户进程从内核中复制数据的过程。

  3. 在 Netty 中,我们看到有使用一个解码器 FixedLengthFrameDecoder,可以用于处理定长消息的问题,能够解决 TCP 粘包读半包问题,十分方便。

(完)

推荐阅读:

两万字深度介绍分布式系统原理!【收藏了~】

2020年最新的常问企业面试题大全以及答案

好文!必须点赞
IO系列(八) -浅析NIO工作原理 现在使用 NIO 的场景越来越多,很多网上的技术框架或多或少的使用 NIO 技术,譬如 Tomcat、Jetty、Netty,学习和掌握 NIO 技术已经不是一个 Java 攻城狮的加分技能,而是一个必备技能。 阅读详情

相关推荐

NIO的多路复用机制

在一次磁盘操作中,CPU不是瓶颈,瓶颈是内存和网络,IO操作,所以redis是通过在提高CPU的利用上,增加处理速率。 一般提高CPU的利用是通过多线程,一般线程数是cpu核数的2倍,但是redis是通过单线程实现的;一方面是因为多线程存在上下文切换(用户态和内核态的切换)消耗问题,另一方面是因为redis采用IO多路复用机制。 面试时,redis被问到了3次,每一次都是一个惨痛的教训,希望读者朋...

u013801987的博客 2950

什么是NIO

1.2 什么是NIO NIO即New IO,这个库是在JDK1.4中才引入的。NIO和IO有相同的作用和目的,但实现方式不同,NIO主要用到的是块,所以NIO的效率要比IO高很多。 在Java API中提供了两套NIO,一套是针对标准输入输出NIO,另一套就是网络编程NIO,本篇文章重点介绍标NIO,关于网络编程NIO请见Java NIO详解(二)。 1.3 流与块的比较 NIO和IO最大的区别是数据打包和传输方式。IO是以流的方式处理数据,而NIO是以块的方式处理数据。 面向流的IO一次一个字节

qq_40826814的博客 4775

Cadence OrCAD: 层次化设计 Hierarchical Design

详细介绍OrCAD的原理图层次化设计方法。

Fantasy237的博客 1万+

NIO的基本介绍

一、什么是NIO Java NIO全称java non-blocking IO, 是指JDK提供的新API。从JDK1.4开始,Java提供了一系列改进的输入/输出的新特性,被统称为NIO(即New IO),是同步非阻塞的 NIO有三大核心部分: Channel(通道), Buffer(缓冲区),Selector(选择器) NIO是面向缓冲区,或者面向块编程的。数据读取到一个它稍后处理的缓冲区,需要时可在缓冲区中前后移动,这就增加了处理过程中的灵活性,使用它可以提供非阻塞式的高伸缩性网络。

莫失莫忘的博客 1万+

别再为环保数采仪通讯发愁!手把手教你用MCGS触摸屏+4G模块发送HJ212报文

本文详细介绍了如何使用MCGS触摸屏配合4G模块高效发送HJ212标准报文,解决工业环保监测中的数据采集与传输难题。从硬件连接到软件配置,再到报文组装与发送策略,提供全流程实用指南,特别针对4G网络环境下的特殊设置给出优化建议,帮助工程师提升数据传输稳定性与效率。

weixin_30847865的博客 389

第5.1节 构网控制:电压源特性与电压调节

摘要: 构网型变流器的核心物理本质是作为可控交流电压源,通过戴维南等效模型(受控电势源+低输出阻抗)自主建立并调节电压,增强电网电压刚度。其电压调节通过无功-电压闭环控制实现,内环为自动电压调节器(AVR),外环为无功-电压下垂特性,模拟同步发电机功能。关键技术包括自适应增益、虚拟阻抗补偿及动态限流策略,以应对弱电网稳定性、故障过流等问题。该设计满足《规范》对电压调节范围、动态无功支撑的要求,是高比例新能源电力系统电压稳定的关键解决方案。

技术工作者 1110

NIO介绍

一、NIO介绍 1、定义 NIO(Non-blocking I/O ,在Java领域,也称为New I/O),是一种同步非阻塞的I/O模型,也是I/O多路复用的基础,已经被越来越多地应用到大型应用服务器,成为解决高并发与大量连接、I/O处理问题的有效方式。 2、概叙 NIO主要有三大核心部分:Channel(通道),Buffer(缓冲区), Selector。传统IO基于字节流和字符流进行操作,而NIO基于Channel和Buffer(缓冲区)进行操作,数据总是从通道读取到缓冲区中,或者从缓冲区写入

qq_33923684的博客 5044

机器视觉避坑指南:为什么你的Halcon划痕检测总漏检?(附优化方案)

本文深入剖析了Halcon在表面划痕检测中漏检率高的常见原因,如灰度值波动、噪声干扰及形态学参数设置不当。针对复杂背景与低对比度划痕,提出了超越官方例程的多尺度纹理分析与特征融合优化方案,旨在帮助开发者构建更鲁棒、稳定的机器视觉检测流程,有效提升检出率。

weixin_29057163的博客 235

面试官:什么是 NIO?NIO 的原理是什么机制?

Java NIO(New I/O)是Java 1.4引入的高性能I/O框架,通过非阻塞、多路复用等机制解决传统BIO在高并发场景下的性能瓶颈。其核心组件包括Buffer(缓冲区)、Channel(通道)和Selector(选择器),实现了单线程管理多连接的能力。NIO采用同步非阻塞I/O模型,底层依赖操作系统的多路复用机制(如epoll),相比BIO显著减少了线程开销和数据拷贝。本文详细解析了NIO的核心概念、工作原理、编程示例及高级特性,并对比了NIO.2(AIO)的异步I/O能力。尽管存在空轮询等潜在问

油墨香^-^的博客 1198

VN5620硬件接口介绍

VECTOR, VN5620, 诊断

Fecostar的博客 7488

智能排班考勤系统原型

可实现从业务预测,到工时预估,再到人员分配全流程自动智能排班。可应用于客服行业或工厂的智能排班系统。

gywm15111336483的专栏 996

面试官扎心一问:NIO的原理是什么机制?

长按识别下方二维码,即可"关注"公众号每天早晨,干货准时奉上!本文作者:依本多情链接:blog.youkuaiyun.com/qq_36520235/article/detai...

Java学习之道 2268

经典损失函数——均方误差(MSE)和交叉熵误差(CEE)的python实现

损失函数(loss function)用来表示当前的神经网络对训练数据不拟合的程度。这个损失函数有很多,但是一般使用均方误差和交叉熵误差等。 1.均方误差(mean squared error) 先来看一下表达式: 用于将的求导结果变成,是神经网络的输出,是训练数据的标签值,k表示数据的维度。 用python实现: def MS...

Answer3664的博客 1万+

面试官我:什么是NIO?NIO的原理是什么机制?我竟然没回答上来...

点击上方 "程序员小乐"关注,星标或置顶一起成长每天凌晨00点00分,第一时间与你相约每日英文Not easily cut open...

程序员小乐 420

单细胞转录组分析(scRNA-seq)

单细胞转录组测序(Single-cell RNA sequencing,scRNA-seq)是一种高通量测序技术,可以在单细胞水平解析基因表达情况,揭示细胞异质性,探索稀有细胞类型,并研究细胞状态转换及动态调控机制。与传统的。

大甘的博客 6150

OV9734 DATASHEET,完整规格书

OV9734完整规格书,包括电气参数,尺寸规格,寄存器配置表等

面试官:什么是NIO?NIO的原理是什么?

来源:https://blog.youkuaiyun.com/qq_36520235/NIO和IO到底有什么区别?有什么关系?首先说一下核心区别:NIO是以块的方式处理数据,但是IO是以最基础的字节...

singwhatiwanna 842

Devexpress16.2.6破解工具

Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具

10 个最高频的 Java NIO 面试题剖析!

NIO 是 Java 面试中的高频知识点,也是大型中间件中,以及网络通讯中常用的技术。而什么是 NIO? NIO 和 BIO、AIO 之间的区别是什么? 什么是同步,异步,阻塞和非阻塞?什么是多路复用器?这一系列问题下来,不少面试候选人直接懵圈。 因此,本场 Chat 将从零开始,通过详细的画图讲解,彻底让大家搞清楚 Java 中围绕 NIO 的各种知识点,让你在面试官的 NIO 连环炮攻击下,泰...

GitChat 1万+

C# WinForm 基于DirectShow.dll编写的程序,可边预览边保存视频,音频和图片

基于微软的DirectShow.dll的二次开发1.自动识别连接的摄像头跟麦克风且可以对其进行选择(默认选中第一个)2.可录制wmv和avi两种格式的视频并且都带有音频,avi可以录制的分辨率和帧数进行选择,wmv默认进行了淸晰度优化如不喜欢可去除代码中有相关提示3.可在预览点开之后进行拍照,也可边录制视频边拍照4.添加了视频和音频的压缩功能(酌情使用)这次二次开发发现C#对DirectShow的相关信息太少,这次做完也不敢藏私共享出来,还望大家指正

BIO NIO AIO之面试官和你

面试官:做个上传文件吧? 你:嗯 面试官:那就说说BIO NIO AIO的概念吧。 你:BIO 同步阻塞 File,输入输出流,HttpUrlConnection NIO 同步非阻塞 Channel Selector Buffer等新抽象,多路服务,提供更接近系统底层的数据操作。 AIO/NIO2 异步非阻塞 基于事件和回调机制,任务完成时,系统回去通知相应的线程 面试官:...

shandeai520的专栏 546

面试官:BIO、NIO、AIO的区别

BIO、NIO、AIO的区别

飞乐鸟的博客 762
上一篇: SpringBoot 控制并发登录的人数教程
下一篇: ping 命令的七种用法,看完瞬间成大神
Java思维导图
博客等级 码龄10年 306粉丝 71原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值