你真的知道 Java NIO 与 IO 的区别吗?

 2022-08-12
原文地址:https://blog.csdn.net/ly0724ok/article/details/116666451

1. 简介

NIO即New IO,JDK1.4中引入的。提供了与标准IO不同的IO工作方式,可替代 标准Java IO 的IO API。

202208122241139891.png

  • Java IO是面向流的,这意味着我们需要每次从流中读取一个或多个字节,直到读取完所有字节;NIO是面向缓冲的,也就是说会把数据读取到一个缓冲区中,然后对缓冲区中的数据进行相应处理。
  • Java IO是阻塞IO,而NIO是非阻塞IO。
    阻塞IO :当一个线程调用read() 或 write()时,该线程被阻塞,直到有一些数据被读取,或数据完全写入,该线程在此期间不能再干任何事情了
    非阻塞IO :一个线程从某通道发送请求读取数据,但是它仅能得到目前可用的数据,如果目前没有数据可用时,就什么都不会获取,而不是保持线程阻塞,所以直至数据变的可以读取之前,该线程可以继续做其他的事情
    -Java NIO中存在一个称为选择器(selector)的东西,它允许你把多个通道(channel)注册到一个选择器上,然后使用一个线程来监视这些通道:若这些通道里有某个准备好可以开始进行读或写操作了,则开始对相应的通道进行读写。而在等待某通道变为可读/写期间,请求对通道进行读写操作的线程可以去干别的事情。

2. NIO核心组件

  • 通道(Channel)

  • 缓冲区(Buffer)

  • 选择器(Selectors)

    202208122241150152.png

基本上,所有的IO和NIO都从一个Channel开始。Channel有点像流。数据可以从Channel读到Buffer中,也可以从Buffer写到Channel中

以下是Java NIO里关键的Buffer实现
ByteBuffer
CharBuffer
DoubleBuffer
FloatBuffer
IntBuffer
LongBuffer
ShortBuffer
这些Buffer覆盖了你能通过IO发送的基本数据类型:byte,short,int,long,float,double和char

Java NIO还有个MappedByteBuffer,用于表示内存映射文件。

Selector

Selector允许单线程处理多个Channel。如果你的应用打开了多个连接(通道),但每一个连接的流量都很低,使用Selector就会很方便。

这是在一个单线程中使用一个Selector处理3个Channel的图示:

202208122241171043.png
要使用Selector,得向Selector注册Channel,然后调用它的select()方法。这个方法会一直阻塞到某个注册的通道有事件就绪。一旦这个方法返回,线程就可以处理这些事件,事件的例子有如新连接进来,数据接送等

Channel:
Java NIO的通道类似流,但又有些不同:

既可以从通道中读取数据,又可以写数据到通道。但流的读写通常是单向的。
通道可以异步的读写。
通道的数据总是要先读到一个Buffer,或者总要从一个Buffer中写入。
正如上面所说,从通道读取数据到缓冲区,从缓冲区写入数据到通道。