最新消息:

网络编程之 IO 与 NIO

Java 190浏览 0评论

基础概念

1、传统 BIO 模型

传统 BIO 是一种同步的阻塞 IO,IO 在进行读写时,该线程将被阻塞,线程处于阻塞 (blocked)状态,无法进行其他操作。

IO 流在读取时,会阻塞。知道发生以下情况:(1)有数据可以读取;(2)独居读取完成;(3)发生异常

2、伪异步 IO 模型

以传统 BIO 模型为基础,通过线程池的方式维护所有的 IO 线程,实现相对搞笑的线程开销及管理。

3、NIO 模型

NIO 模型时一种同步非阻塞 IO,主要有三大核心部分:Channel(通道)、Buffer(缓冲区)、Selector(多路复用器)。

传统 IO 基于字节流和字符流进行操作,而 NIO 基于 Channel 和 Buffer 进行操作,数据总是从通道读取到缓冲区,或者从缓冲区写入到通道中。

Selector 用于监听多个通道的事件,如连接断开、数据到达。因此,单个线程可以监听多个数据通道。

IO 与 NIO 区别

IO  与 NIO 最大的区别就是,IO 是面向流,NIO 是面向缓冲区的。

Java IO 面向流意味着每次从流中读一个或多个字节,直到读取所有字节,它们没有被缓存在任何地方。此外,它不能前后移动流中的数据。如果需要前后移动从流中读取的数据,需要先将它存入缓冲区。

NIO 的缓冲导向方法略有不同。数据读取到一个它稍后处理的缓冲区,需要时可以在缓冲区中前后移动,者增加了处理过程的灵活性。

但是,还需要检查是否该缓冲区中包含所需要处理的数据。而且,需要确保当更多的数据读入缓冲区时,不要覆盖缓冲区里尚未处理的数据。

IO 的各种流是阻塞的。这意味着,当一个线程调用 read() 或 write()时,该线程被阻塞,直到有一些数据被读取,或数据完全写入。该线程再次期间不能再干任何事情了。

NIO 的非阻塞模式,使一个线程从某通道发送请求读取数据,但是它仅能得到目前可用的数据,如果目前没有数据可用时,就说明都不会获取。而不是保持线性阻塞,所以直至数据变得可以读取之前,该线程可以继续做其他的事情。非阻塞写也是一样。一个线程请求写入一些数据到某通道,但不需要等待它完全写入,这个线程同时可以去处理其他的事情。线程通常讲非阻塞 IO 的空闲时间用于其他通道上执行 IO 操作,所以一个单独的线程现在可以管理多个输入和输出通道。

NIO 优点

1、通过 Channel 注册到 Selector 的状态来实现一种客户端与服务端的通信

2、 Channel 中数据的读取时通过 Buffer,一种非阻塞的方式读取

3、Selector 多路复用器 单线程模型,线程的资源开销相对较小

Channel

Channel 是一个双向通道,与传统 IO 操作只允许单向的读写不同的是,NIO 的 Channel 允许在一个通道上进行读和写的操作。

传统 IO 操作对 read() 或 write() 方法的调用,可能会因为没有数据可读 / 可写 而阻塞,直到有数据响应。也就是说读写数据的 IO 调用,可能会无限期的阻塞等待,效率依赖网络传输的速度。最重要的是在调用一个方法前,无法直到是否会被阻塞。

NIO 的Channel 抽象了一个重要特征就是可以通过配置它的阻塞行为,来实现非阻塞式的通道。

Buffer

Buffer 顾名思义,是一个缓冲区,实际上是一个容器,一个连续的数组。Channel 提供从文件、网络读取数据的渠道,但是读写的数据必须经过 Buffer。

12.jpg

Buffer 缓冲区本质上是一块可以写入数据,然后可以从中读取数据的内存块。这块内存被包装成 NIO Buffer 对象,并提供了一组方法,用来方便的访问该模块内存。

为了理解 Buffer 的工作原理,需要熟悉它三个属性:capacity、position 和 limit。

position 和 limit 的含义取决于 Buffer 处在读模式还是写模式。不管 Buffer 处在什么模式,capacity 的含义总是一样的:

11.jpg

capacity:

作为一个内存块,Buffer 有固定的大小值,也叫做 capacity,只能网其中写入 capacity 个 byte、long、char 等类型。一旦 Buffer 满了,需要将其清空才能继续写数据。

position:

当写数据到 Buffer 中时,position 表示当前的位置。初始的 position 值为0,当写入一个字节数据到 Buffer 中后,position 会向前移动到下一个可插入数据的 Buffer 单元。position 最大可为 capacity -1 .当读取数据时,也是从某个特定位置读,将 Buffer 从写模式切换到读模式,position 会被重置为0。当从Buffer 的position 处读取一个字节数据后,position 向前移动到下一个可读的位置。

limit:

在写模式下,Buffer 的 limit 表示最多能往 Buffer 中写入多少数据。写模式下,limit 等于Buffer 的capacity。当切换Buffer到读模式时,limit 表示最多可读到的数据。因此,当切换 Buffer 到读模式时,limit 会被设置成写模式下的 position 值。换而言之,一定能读到的写入的所有数据。

转载请注明:微刻 blog.wecot.cn » 网络编程之 IO 与 NIO

发表我的评论
取消评论
表情

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址