其实这个专栏 从一开始就是准备讲NIO的。
但是前五篇还是实践了很多BIO的代码,主要是为了体会到同步阻塞迈向非阻塞的思想变化。更好的理解NIO。
NIO
先来一段比较形象的NIO解释:
Java的NIO(New Input/Output)是一种提供了更高效、更灵活的I/O(输入/输出)操作方式的编程接口。它引入了一套全新的非阻塞I/O模型,使得Java程序能够更好地处理大量的并发连接。
NIO与传统的IO相比
与传统的Java
I/O(IO)相比,NIO的主要特点是采用了基于通道(Channel)和缓冲区(Buffer)的方式进行数据传输。这种方式可以更高效地处理数据,尤其在需要处理大量并发连接时表现更出色。举个例子来说明,假设你正在开发一个服务器程序,需要同时处理多个客户端的请求。使用传统的Java
IO,你可能需要为每个客户端连接创建一个线程,而线程的创建和管理会带来一定的开销。而使用Java
NIO,你可以通过单线程就能处理多个客户端连接。在Java
NIO中,你可以创建一个ServerSocketChannel来监听客户端的连接请求,一旦有连接进来,你可以通过调用accept方法来接收连接,并将连接注册到Selector上。Selector是NIO中的核心概念,它可以同时监控多个通道的事件,比如连接、读、写等。一旦某个通道上发生了感兴趣的事件,你可以通过Selector进行处理。在处理连接时,可以使用ByteBuffer作为缓冲区,将数据从通道读取到缓冲区中,或者从缓冲区写入到通道中。这种方式可以避免频繁的系统调用,提高数据传输的效率。
总结来说,Java
NIO通过引入通道和缓冲区的概念,提供了一种高效、非阻塞的I/O操作方式,适用于处理大量并发连接的场景。它可以减少线程的创建和管理开销,提高系统的性能和可伸缩性。
这里大家要理解NIO和BIO的区别,前几篇中已经通过实践 体会到了什么是:
同步阻塞 ,就是在BIO下通信的时候 BIO一个线程监听数据流,当客户端还没有发送数据的时候,这时候监听的线程就一直卡在那里,等到天长地久。 它不能去做其他的事情,
虽然我们优化了这个过程,引入了多线程,就是每次来一个请求,我们就开一个新线程,但是这样只是增强了它的处理能力,并没有改变同步阻塞的本质
因为你不管开多少个线程,在每个线程之中还是在同步阻塞的等客户端发消息。
而NIO 不是这样,你可以理解为 NIO只有一个线程,它面对的不是流(bio一般都是监听流的数据) 它面向的是缓冲区和管道, 使用选择器(单线程)可以轮询监听多个管道 这时候它发现哪个管道上有数据过来了 它就处理哪个
通道 Channel
Channel 是一个NIO核心概念。 它实在java.nio中定义的。
channel简单来说 它是IO源与目标中的一个连接, 你可以把它类比为BIO中的stream。
但是流可以之间访问数据,比如上一篇中 我们使用datainputsteam来之间访问文件数据, channel不可以 它只能与buffer交互, 你可以形象的在脑海中想象一个桥 channel,在桥的两个尽头是是一段接壤的路 (buffer)
那你会好奇了 这个东西比传统的流高大上在那里呢???
- 它是双向的,它既可以读也可以写。 你发现没有 channel 没有inputchannel ,outputchannel的说法。
- 它可以异步读写数据,意味着我们不需要BIO那样等数据来我们啥都不能干,我们监听的时候 可以继续往下走,等数据来了 它会单独 开一个线程去处理
- 和1相似 它可以从bufffer读数据 也可以写数据到缓冲
常用的channel实现类
FileChannel:用于对文件进行读写操作的通道。
SocketChannel:用于进行TCP网络套接字的读写操作。它可以连接到远程主机并通过网络发送和接收数据。
ServerSocketChannel:用于监听传入的TCP连接请求,它为每个传入的连接创建一个SocketChannel。
DatagramChannel:用于进行UDP网络套接字的读写操作。它可以通过网络发送和接收数据报。