从计算机操作模型认识NIO

相信很多朋友和我一样,可能对NIO有过了解,但是你真的很清楚是怎么回事吗?或者能说清楚什么是NIO吗?写这篇文章,是自己学习的一个输出,同时也想和同样有困惑的同学做一个分享和讨论。

一个非常重要的理念

在所有我们的应用程序,我们的程序是对计算机硬件操作的抽象,或者说是一个操作模型。(在我们理解NIO中非常重要)

计算机IO操作模型

在这里插入图片描述
说明:
用户空间:在java应用系统中,应该对应JVM内存模型。
内核空间:操作系统所在区域
缓冲区及操作是所有I/O的基础,进程执行I/O操作,归结起来就是向操作系统发出请求,让它要么把缓冲区里的数据排干(写),要么把缓冲区填满(读)

那什么是IO操作

在JAVA中,我们关注的有磁盘读写和网络读写。
磁盘IO:操作系统将磁盘中的数据读取到内核空间的缓冲区,当缓冲区写满后,拷贝到JVM内存中。
网络IO: 将网卡中的数据读取到内核空间的缓冲区,当缓冲区写满后,拷贝到JVM内存中。

大家非常熟悉的几个模型

BIO:
在这里插入图片描述
说明:比如JAVA 中InputStream.read()操作去磁盘读取1024byte,这时候编译器生成的指令,会告诉CPU去某个磁盘位置读取1024个字节到内核空间的缓冲区中。传统BIO中,通过流的方式读取数据内容,也就是说每次交互读取一个字节,不断的通过流去读取这个1024个字节,在读取过程中,这个应用进程是一直在等待,直到读完全部的1024字节,该线程的等待就是一个阻塞模式。

NIO:(New IO)
在这里插入图片描述
注意:这张图中多次发送系统调用,是需要应用程序主动触发的。

说明:同样,JAVA 中InputStream.read()操作去磁盘读取1024byte,这时候编译器生成的指令,会告诉CPU去某个磁盘位置读取1024个字节到内核空间的缓冲区中。NIO中,通过Channel的方式读取数据内容(注意我们开篇提到的理念,Channel只是我们java api中定义的一个模型,生成编译指令告诉CPU我们如何操作),操作系统会去帮我们将数据内容读取到缓冲区,但当我们的channel去读取时,发现缓冲区中并没有1024个字节数据内容时,会直接返回。

这个图其实表示的是我们怎么去完全读取数据内容的图,其中多次发送系统调用,是通过JAVA代码去操作的,而不是自动触发的(这里我之前一直认为是操作系统自己触发的)

为了解决应用程序需要不断的去触发系统调用,JAVA NIO中采用了多路复用模型

多路复用IO
在这里插入图片描述
说明:Select模型中,将channel注册到SelectionKey集合中,然后Selector通过监听SelectionKey集合中每一个channel的状态,即判断每个channel对应的缓存区是否写满数据,如果准备就绪,就通知channel去读取缓冲区中的数据内容。

异步IO:
在这里插入图片描述
说明:异步io,在数据没有准备完成直接返回,而后完全交给操作系统,当操作系统写满缓存区后,主动通知channel发送一个信号,通知channel去读取数据内容。

总结

其实IO操作一直是操作系统在处理的,也一直是阻塞的,这里面涉及计算机总线的知识。我们从字面去理解阻塞IO和非阻塞IO很容易产生误解。

这里我们其实是从应用进程或线程的角度出发:

当需要等待数据读取到JVM内存中,然后才能继续后续操作,我们认为就是阻塞的。
当我们的应用进程或者线程,不需要等待数据读取到JVM内存中,就可以进行其他操作,我们认为就是非阻塞的。

BIO和NIO的区别又在哪里,IO操作都是会写到缓存区的。(此时,我们又要提到开篇说的JAVA中的API是对硬件操作的抽象了),这里BIO我们通过流去操作的时候,我们生产的编译指令告诉操作系统,需要等待缓冲区数据完全写满,注意这里等待,而NIO模型中,我们的API生成的编译指令,告诉操作系统不需要。我认为这里是最重要的区别。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值