一、IO模型
五种:阻塞IO、非阻塞IO、多路复用IO、信号驱动IO、异步IO
1.阻塞IO:一个应用程序执行I/O操作时,会被阻塞,直到数据准备好或操作完成。这种模型通常简单易用,但会造成资源浪费。因为CPU在等待I/O操作完成时无法做其他有用的工作。
2.非阻塞IO模型:应用程序执行I/O操作时不会被阻塞,可以立即返回,然后定期检查操作是否完成。这种模型需要应用程序不断轮询状态,可能会降低性能并增加复杂性。
3.I/O复用模型:通过select、poll或epoll等机制,应用程序可以同时监视多个I/O事件,当其中任何一个事件就绪时才进行处理。这种模型避免了阻塞和循环轮询的缺点,提高了效率。
4.信号驱动I/O模型:应用程序告知内核去等待某个事件发生,并且可以同时进行其他操作。当事件发生时,内核发送信号通知应用程序进行处理。这种模型适用于处理少量的连接和事件。
5.异步I/O模型:应用程序发起一个 I/O 操作后,可以继续执行其他操作,当 I/O 操作完成时会通知应用程序。这种模型减少了应用程序与内核的交互次数,提高了性能。
二、IO多路复用(select、epoll、poll)
- select 是 Unix 系统中最早的 I/O 多路复用技术。它允许一个线程同时监视多个文件描述符,并等待某个文件描述符上的 I/O 事件(如可读、可写或异常)。select 的主要问题是性能受限,特别是在处理大量文件描述符时。这是因为它使用一个位掩码来表示文件描述符集,每次调用都需要传递这个掩码,并在内核和用户空间之间进行复制。
- poll 是对 select 的改进。它使用一个文件描述符数组而不是位掩码来表示文件描述符集。这样可以避免 select 中的性能问题。然而,poll 仍然需要遍历整个文件描述符数组,以检查每个文件描述符的状态。因此,在处理大量文件描述符时,性能仍然受限。
- epoll 是 Linux 中的一种高性能 I/O 多路复用技术。它通过在内核中维护一个事件表来避免遍历文件描述符数组的性能问题。当某个文件描述符上的 I/O 事件发生时,内核会将该事件添加到事件表中。应用程序可以使用 epoll_wait 函数来获取已准备好的 I/O 事件,而无需遍历整个文件描述符集。这种方法大大提高了在大量并发连接下的性能。
三、NIO与IO的区别
NIO就是New IO,这个库是在jdk1.4中引入。NIO和IO有相同的作用和目的,但实现方式不同,NIO主要用到的是块,所以NIO的效率较高。在JAVA API中提供了两套NIO,一套是针对标准输入输出NIO,另一套是网络编程NIO。
四、NIO和IO的适用场景
NIO是为了弥补传统IO的不足而诞生的,NIO也有缺点,因为NIO是面向缓冲区的操作,每一次的数据处理都是对缓冲区进行的,在数据处理之前必须要判断缓冲区的数据是否完整或者已经读取完毕,如果没有,假设只读取了一部分,那么对不完整的数据处理没有任何意义。所以每次数据处理之前都要检测缓冲区数据。
- 如果需要管理同时打开成千上万个连接,这些连接每次只是发送少量的数据,例如聊天服务器,这时候用NIO处理数据。
- 如果是少量连接,而这些连接每次要发送大量的数据,这时候采用IO更合适。
- 使用哪种处理数据,需要再数据的响应等待时间和检查缓冲区数据的时间上作对比。