当前位置: 首页 > 图灵资讯 > 技术篇> Java IO模型(BIO | NIO | AIO)

Java IO模型(BIO | NIO | AIO)

来源:图灵教育
时间:2023-09-05 11:55:22

Java IO 模型之 BIO,NIO,AIO (qq.com)

Java 中 BIO、NIO、AIO 的区别?

五种常见的IO模型

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

让我们谈谈Java中三种常见的IO模型

BIO(Blocking I/O)

BIO属于同步阻塞IO模型

在IO模型中,应用程序启动read调用后,直到内核将数据复制到用户空间。

图源:《深入拆解Tomcat & Jetty》

当客户端连接数量不高时,没有问题。但面对10万甚至100万的连接,传统的BIO模型无能为力。

NIO(Non-blocking/New I/O)

NIO 有三个核心组件:Channel(通道), Buffer(缓冲区),Selector(多路复用器)

  • Selector:Selector允许单线程处理多个Chanel。若应用程序打开多个连接(通道Chanel),但每个连接的流量都很低,使用Selector会很方便。如果你想使用Selector,你必须向Selector注册Chanel,然后调用他的Select方法。这种方法总是会阻止某个注册渠道发生事件。该方法一旦返回,线程就可以处理这些事件。
  • Channel:基本上所有的IO都是从NIO的Chanel开始的,Chanel有点像流,数据可以从Chanel读到Buffer,也可以从Buffer写到Chanel。
  • Buffer:缓冲区本质上是一个可以读写数据的内存块,可以理解为一个容器对象(包括数据),它提供了一组更容易使用内存块的方法。缓冲区对象内置了一些机制,可以跟踪和记录缓冲区的状态变化。chanel提供从文件和网络读取数据的渠道,但读取或写入的数据必须通过buffer。

应用场景:NIO适用于连接数量多、连接短的架构,如聊天服务器、弹幕系统、服务器间通信等。NIO的编程更为复杂。

NIO底层在JDK1.4版本中使用linux的核心函数select()或poll()来实现。selector每次都会轮流询问所有的sockchanel,看看哪个chanel有读写事件。如果有,就处理。如果没有,就继续遍历JDK1.基于事件的响应机制开始引入epoll优化NIO。

图片

Selector类似于观察者。只要我们告诉SelectorSelechanel需要探测,我们就会做其他事情。当事情发生时,他会通知我们传回一组SelectionKey(Linux核心中的rdlist就绪事件列表)。当我们读到这些Key时,我们将获得我们刚刚注册的Selechanel。然后,我们从这个Chanel中读取和处理这些数据。Selector的内部原理实际上是做一个注册的Chanel(SocketChannel)一旦轮到Chanel注册,比如数据来了,他就会站起来报告,交出一把Key,通过Key阅读Chanel的内容。

图片

AIO(Asynchronous I/O,NIO 2.0)

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

AIO模型主要基于事件和回调机制。当I/O操作完成时,操作系统会通知应用程序,然后应用程序会执行相应的回调函数进行处理。在AIO模型中,处理大量连接只需要少量线程,大大提高了系统的并发处理能力。

一般适用于连接数多、连接时间长(重操作)的应用。

然而,AIO模型的兼容性相对较差,需要操作系统的支持,不同的操作系统以不同的方式实现AIO。

图片

BIO、 NIO、 AIO 对比

图片

为什么Netty使用Nettty为什么使用Nettty NIO 而不是 AIO ?

在 Linux 系统上,AIO 底层实现仍在使用中 Epoll,没有很好的实现 AIO,因此,在性能上没有明显的优势。

Netty 是异步非阻塞框架,Netty 在 NIO 上面做了很多异步包装。