Java基础之IO模型

Java基础之IO模型面试喜欢问的操作系统问题:BIO,NIO,AIO

I/O

I/O(input / output) 即 输入/输出

从计算机结构的角度来解读I/O。
根据冯·诺伊曼,计算机结构分为5大部分:运算器、控制器、存储器、输入设备、输出设备。

在这里插入图片描述
输入设备(比如键盘)和输出设备(比如显示器)都输入外部设备。网卡、硬盘这种即可以作为输入设备也可以作为输出设备。
输入设备向计算机输入数据,输出设备接收计算机输出的数据。

从计算机结构的角度来看,I/O描述了计算机系统与外部设备之间的通信过程。

再从应用程序的角度来看I/O。
为了保证操作系统的稳定性和安全性,一个进程的地址空间划分为用户空间(User space)内核空间(Kernel space)。并且用户空间的程序不能直接访问内核空间。


我们平时运行的应用程序都运行再用户空间,只有内核空间才能运行系统态级别的资源有关的操作,比如如文件管理、进程通信、内存管理等。就是说,我们要想进行IO操作,一定要依赖内核空间能力

当要想执行IO操作,由于没有执行这些操作的权限,只能发起系统用请求操作系统帮忙完成。所以,用户进程想要执行IO操作的话,必须通过系统调用来间接访问内核空间。

我们平时接触最多的就是磁盘IO(读写文件)网络IO(网络请求和响应)
从应用程序的角度来看,应用程序对操作系统的内核发起IO调用(系统调用),操作系统负责的内核执行具体的IO操作。就是说,应用程序实际只是发起了IO操作的调用而已,具体IO的执行是由操作系统的内核来完成的。

当应用程序发起I/O调用后,会发生两个步骤:

  1. 内核等待I/O设备准备好数据
  2. 内核将数据从内核空间拷贝到用户空间。

常见的IO模型

UNIX系统下,IO模型一共有5种:同步阻塞I/O、同步非阻塞I/O,I/O多路复用、信号驱动I/O和异步I/O。这也是常用的5种IO模型。

Java中3种常见的IO模型

BIO(Blocking I/O)

BIO属于同步阻塞I/O模型

同步阻塞IO模型,应用程序发起read调用后,会一直阻塞,直到在内核把数据拷贝到用户空间。
同步阻塞
在客户端连接数量不高的情况下,没有问题,但,当面对十万甚至百万级别连接的时候,传统的BIO模型就无能为力了,所以,需要用更高效的I/O处理模型来应对更高的并发量。

NIO(Non-blocking/New I/O)

Java中的NIO是在Java 1.4引入,对应java.io包,提供了ChannelSelector,Buffer等抽象。NIO中的N理解为Non-blocking,不单纯是New,
它支持面向缓冲,基于通道的I/O操作方法,对于高负载、高并发的网络与应用,应使用NIO。
Java中的NIO可以看作为是I/O多路由复用。也有人认为,Java中的NIO属于同步非阻塞IO模型。
同步非阻塞模型
同步非阻塞
同步非阻塞IO模型中,应用程序会一直read调用,等待数据从内核空间拷贝到用户空间的这段时间里,线程依然是阻塞的,直到在内核把数据拷贝到用户空间。
相比于同步阻塞IO模型,同步非阻塞IO模型确实有了很大改进。通过轮询操作,避免了一直阻塞。
但也同样存在着问题:应用程序不断进行I/O系统调用轮询数据是否已经准备好的过程十分耗费CPU资源

这个时候,I/O多路由复用模型就登场了。
多路由复用
IO多路复用模型中,线程首先发起select调用,询问内核数据是否准备就绪,等内核数据准备好了,用户线程再发起read调用。read调用的过程(数据从内核空间->用户空间)还是阻塞的。

支持IO多路复用的系统调用,有select,epoll… seclet系统调用,是目前几乎在所有的操作系统上都支持。

  • select调用: 内核提供的系统调用,支持依次查询多个系统调用的可用状态,几乎所有的操作系统都支持。
  • epoll调用: linux2.6内核,属于select调用的增强版,优化了IO的执行效率。

IO多复用模型,通过减少无效的系统调用,减少了对CPU资源的消耗。

java中的NIO,有一个非常重要的选择器(Selector),也叫 多路复用器。 通过它,只要一个线程便可管理多个客户端连接,当客户端数据到了后,才会为其服务。
选择器

AIO(Asynchronous I/O)

AIO也就是NIO 2。Java 7 中引入了NIO的改进版,它是异步IO模型。

异步IO是基于事件回调机制实现的,也就是应用操作之后会直接返回,不会堵塞在那里,当后台处理完成,操作系统会通知相应的线程进行后续的操作。
异步
至今来说AIO的应用还不广泛,Netty也尝试使用AIO,不过放弃了,原因是:使用AIO后,在Linux上的性能并没有提升多少。

总结(BIO,BIO,AIO有什么区别)

  • BIO(Blocking I/O):服务器实现模式为一个连接一个线程,客户端有连接请求时服务器就要启动一个线程进行处理,若这个连接不做任何操作还造成不必要的线程开销,可以通过线程池机制来改善。BIO方式适合连接数目小且固定的架构,这种方式对服务器资源要求比较高,并发局限于应用中,在JDK1.4以前时唯一的IO。
  • NIO(NEW I/O):服务器实现模式为一个请求一个线程,客户端发送的连接请求都会注册到多路复用器上,多路复用器轮询到连接有IO请求时才启动一个线程进行处理,NIO方式适合用于连接数目多且连接时间短(轻操作)的架构,如聊天服务器,并发局限于应用中,编程复杂,JDK 1.4之后开始支持。
  • AIO(Asynchronous I/O):服务器实现模式为一个有效请求一个线程,客户端的IO请求都是由操作系统先完成再通知服务器用其启动线程进处理,AIO适合用于连接数目多且连接比较长(重操作)的架构,如相册服务器,充分调用OS参与并发操作,编程复杂,JDK 1.7开始支持。

经典例子解析理解

BIO: 来到厨房,开始烧水NIO,并坐在水壶面前一直等待水烧开。
NIO: 来到厨房,开AIO烧水,但不坐在水壶面前一直等,而去做其他事,然后每隔几分钟到厨房看一下有没有烧开。
AIO: 来到厨房,开始烧水,不一直等待水烧开,而是坐在水壶上面装个开关,水烧开之后它会通知我们。

今天的文章Java基础之IO模型分享到此就结束了,感谢您的阅读,如果确实帮到您,您可以动动手指转发给其他人。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
如需转载请保留出处:https://bianchenghao.cn/32155.html

(0)
编程小号编程小号

相关推荐

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注