乐趣区

关于后端:NIO-和-IO-有什么区别

首先说一下外围区别:

  1. NIO 是以块的形式解决数据,然而 IO 是以最根底的字节流的模式去写入和读出的。所以在效率上的话,必定是 NIO 效率比 IO 效率会高出很多。
  2. NIO 不在是和 IO 一样用 OutputStream 和 InputStream 输出流的模式来进行解决数据的,然而又是基于这种流的模式,而是采纳了通道和缓冲区的模式来进行解决数据的。
  3. 还有一点就是 NIO 的通道是能够双向的,然而 IO 中的流只能是单向的。
  4. 还有就是 NIO 的缓冲区(其实也就是一个字节数组)还能够进行分片,能够建设只读缓冲区、间接缓冲区和间接缓冲区,只读缓冲区很显著就是字面意思,间接缓冲区是为放慢 I/O 速度,而以一种非凡的形式调配其内存的缓冲区。
  5. 补充一点:NIO 比传统的 BIO 外围区别就是,NIO 采纳的是多路复用的 IO 模型,一般的 IO 用的是阻塞的 IO 模型,两个之间的效率必定是多路复用效率更高

先理解一下什么是通道,什么是缓冲区的概念

通道是什么意思?

通道是对原 I/O 包中的流的模仿。到任何目的地 (或来自任何中央) 的所有数据都必须通过一个 Channel 对象(通道)。

一个 Buffer 本质上是一个容器对象。发送给一个通道的所有对象都必须首先放到缓冲区中;同样地,从通道中读取的任何数据都要读到缓冲区中。Channel 是一个对象,能够通过它读取和写入数据。拿 NIO 与原来的 I/O 做个比拟,通道就像是流。

正如后面提到的,所有数据都通过 Buffer 对象来解决。您永远不会将字节间接写入通道中,相同,您是将数据写入蕴含一个或者多个字节的缓冲区。同样,您不会间接从通道中读取字节,而是将数据从通道读入缓冲区,再从缓冲区获取这个字节。

缓冲区是什么意思?

Buffer 是一个对象,它蕴含一些要写入或者刚读出的数据。在 NIO 中退出 Buffer 对象,体现了新库与原 I/O 的一个重要区别。在面向流的 I/O 中,您将数据间接写入或者将数据间接读到 Stream 对象中

在 NIO 库中,所有数据都是用缓冲区解决的。在读取数据时,它是间接读到缓冲区中的。在写入数据时,它是写入到缓冲区中的。任何时候拜访 NIO 中的数据,您都是将它放到缓冲区中。

缓冲区本质上是一个数组。通常它是一个字节数组,然而也能够应用其余品种的数组。然而一个缓冲区不 仅仅 是一个数组。缓冲区提供了对数据的结构化拜访,而且还能够跟踪零碎的读 / 写过程

缓冲区的类型:

ByteBuffer  
CharBuffer  
ShortBuffer  
IntBuffer  
LongBuffer  
FloatBuffer  
DoubleBuffer

NIO 的底层工作原理

先来理解一下 buffer 的工作机制:

  • capacity 缓冲区数组的总长度
  • position 下一个要操作的数据元素的地位
  • limit 缓冲区数组中不可操作的下一个元素的地位,limit<=capacity
  • mark 用于记录以后 position 的前一个地位或者默认是 0

1. 这一步其实是当咱们刚开始初始化这个 buffer 数组的时候,开始默认是这样的

2、然而当你往 buffer 数组中开始写入的时候几个字节的时候就会变成上面的图,position 会挪动你数据的完结的下一个地位,这个时候你须要把 buffer 中的数据写到 channel 管道中,所以此时咱们就须要用这个 buffer.flip() 办法,

3、当你调用完 2 中的办法时,这个时候就会变成上面的图了,这样的话其实就能够晓得你刚刚写到 buffer 中的数据是在 position—->limit 之间,而后下一步调用clear()

4、这时底层操作系统就能够从缓冲区中正确读取这 5 个字节数据发送进来了。在下一次写数据之前咱们在调一下 clear() 办法。缓冲区的索引状态又回到初始地位。(其实这一步有点像 IO 中的把转运字节数组 char[] buf = new char[1024] 有余 1024 字节的局部给强制刷新进来的意思)

补充:

1、这里还要阐明一下 mark,当咱们调用 mark() 时,它将记录以后 position 的前一个地位,当咱们调用 reset 时,position 将复原 mark 记录下来的值

2.clear()办法会:清空整个缓冲区。position 将被设回 0,limit 被设置成 capacity 的值(这个集体的了解就是当你在 flip()办法的根底上曾经记住你写入了多少字节数据,间接把 position 到 limit 之间的也就是你写入曾经记住的数据给“复制”到管道中)

3. 当你把缓冲区的数局写入到管道中的时候,你须要调用 flip()办法将 Buffer 从写模式切换到读模式,调用 flip()办法会将 position 设回 0,并将 limit 设置成之前 position 的值。buf.flip();(其实我集体了解的就相当于先记住缓冲区缓冲了多少数据)

退出移动版