关于IO的一些基本概念
- 阻塞和非阻塞的区别:请求方请求后能否做其它事。
- 阻塞IO:发起IO请求后,请求线程被挂起一直等待实际IO操作完成,返回数据。
- 非阻塞IO:发起IO请求后,请求线程不会等待实际IO操作完成,立即返回一个标志信息。
- 同步和异步的区别:请求方是否需要等待结果返回。
- 同步IO:线程请求后,等待结果返回。(图中的多次问询并不必要)
- 异步IO:线程请求后,无需等待,接收方处理完后主动通知。
- 同步和异步的区别:请求方是否需要等待结果返回。
BIO是什么?
概念
- BIO ,全称 Block-IO ,是一种阻塞 + 同步的通信模式。(其实就是传统的IO)
- 是一个比较传统的通信方式,模式简单,使用方便。但并发处理能力低,通信耗时,依赖网速。
原理
- 服务器通过一个 Acceptor 线程,负责监听客户端请求和为每个客户端创建一个新的线程进行链路处理。典型的一请求一应答模式。
- 若客户端数量增多,频繁地创建和销毁线程会给服务器打开很大的压力。后改良为用线程池的方式代替新增线程,被称为伪异步 IO 。
小结
BIO 模型中,通过 Socket 和 ServerSocket 实现套接字通道的通信。阻塞,同步,建立连接耗时。
NIO 是什么?
概念
- NIO ,全称 New IO ,也叫 Non-Block IO ,是一种非阻塞 + 同步的通信模式。
原理
- 客户端和服务器之间通过 Channel 通信。NIO 可以在 Channel 进行读写操作。这些 Channel 都会被注册在 Selector 多路复用器上。Selector 通过一个线程不停地轮询这些 Channel ,找出已经准备就绪的 Channel 执行 IO 操作,从而实现非阻塞。
- 几个重要点:
- 缓冲区 Buffer :它是 NIO 与 BIO 的一个重要区别。
- BIO 是将数据直接写入或读取到流 Stream 对象中。
- NIO 的数据操作都是在 Buffer 中进行的。Buffer 实际上是一个数组。Buffer 最常见的类型是ByteBuffer。
- 通道 Channel :和流 Stream 不同,通道是双向的。NIO可以通过 Channel 进行数据的读、写和同时读写操作。
- 通道分为两大类:一类是网络读写(SelectableChannel),一类是用于文件操作(FileChannel)。SocketChannel 和 ServerSocketChannel都是SelectableChannel 的子类。
- 多路复用器 Selector :NIO 编程的基础。多路复用器提供选择已经就绪的任务的能力:就是 Selector 会不断地轮询注册在其上的通道(Channel),如果某个通道处于就绪状态,会被 Selector 轮询出来,然后通过 SelectionKey 可以取得就绪的Channel集合,从而进行后续的 IO 操作。
- 缓冲区 Buffer :它是 NIO 与 BIO 的一个重要区别。
小结
NIO 模型中通过 SocketChannel 和 ServerSocketChannel 实现套接字通道的通信。非阻塞,同步,避免为每个 TCP 连接创建一个线程。
AIO 是什么?
概念
- AIO ,全称 Asynchronous IO ,也叫 NIO2 ,是一种非阻塞 + 异步的通信模式。在 NIO 的基础上,引入了新的异步通道的概念,并提供了异步文件通道和异步套接字通道的实现。
原理
- AIO 并没有采用 NIO 的多路复用器,而是使用异步通道的概念。其 read,write 方法的返回类型,都是 Future 对象。而 Future 模型是异步的,其核心思想是:去主函数等待时间。
小结
- AIO 模型中通过 AsynchronousSocketChannel 和 AsynchronousServerSocketChannel 实现套接字通道的通信。非阻塞,异步。
总结
BIO/NIO的区别
- 线程模型不同
- BIO:一个连接一个线程,客户端有连接请求时服务器端就需要启动一个线程进行处理。所以,线程开销大。可改良为用线程池的方式代替新创建线程,被称为伪异步 IO 。
- NIO:多个连接一个线程,客户端发送的连接请求都会注册到多路复用器上,多路复用器轮询到连接有新的 I/O 请求时,才启动一个线程进行处理。
- BIO 是面向流( Stream )的,而 NIO 是面向缓冲区( Buffer )的。
- BIO 的各种操作是阻塞的,而 NIO 的各种操作是非阻塞的。
- BIO 的 Stream 是单向的,而 NIO 的 Channel 是双向的。
三者比较
- 需要注意的是,虽然图中说 NIO 的性能比不上AIO,但是在绝大多数我们日常业务场景,NIO 和 AIO 的性能差距实际没这么大。在 Netty5 中,基于 AIO 改造和支持,最后发现,性能并没有想象中这么强悍,所以 Netty5 被废弃,而是继续保持 Netty4 为主版本,使用 NIO 为主。