Java IO 与 NIO 对比

2025年3月17日 | 阅读 3 分钟

让我们看一下表格,展示 Java IO 和 NIO 的主要区别

IONIO
它基于阻塞式 I/O 操作它基于非阻塞式 I/O 操作
它是面向流的它是面向缓冲区的
没有 Channel有 Channel 用于非阻塞式 I/O 操作
没有 Selector有 Selector 用于非阻塞式 I/O 操作

阻塞式 vs. 非阻塞式 I/O

阻塞式 I/O

阻塞式 IO 在返回之前会等待数据被写入或读取。Java IO 的各种流都是阻塞的。这意味着当线程调用 write() 或 read() 时,线程会一直阻塞,直到有数据可读或数据完全写入。

非阻塞式 I/O

非阻塞式 IO 在返回之前不会等待数据被读取或写入。Java NIO 的非阻塞模式允许线程请求将数据写入 Channel,而无需等待其完全写入。在此期间,线程可以继续执行其他任务。


面向流 vs. 面向缓冲区

面向流

Java IO 是面向流的 I/O,意味着我们需要一次从流中读取一个或多个字节。它使用流在数据源/接收器和 Java 程序之间传输数据。使用此方法的 I/O 操作速度较慢。

让我们看看 Java 程序中使用输入/输出流的数据流

Java Nio tutorial6

面向缓冲区

Java NIO 是面向缓冲区的 I/O 方法。数据被读取到缓冲区中,然后通过 Channel 对其进行进一步处理。在 NIO 中,我们使用 Channel 和 Buffer 进行 I/O 操作。

Channel 和 Stream 的主要区别是

  • Stream 只能用于 **单向** 数据传输。
  • Channel 提供了 **双向** 数据传输功能。

因此,通过在 Java NIO 中引入 Channel,可以执行非阻塞式 I/O 操作。

让我们看看 Channel、Buffer、Java 程序、数据源和数据接收器之间的交互

Java Nio tutorial7

通道

在 Java NIO 中,Channel 是在实体和字节缓冲区之间高效地传输数据的媒介。它从实体读取数据并将其放入缓冲区块中供消耗。

Channel 作为 Java NIO 提供的网关,用于访问 I/O 机制。通常,Channel 与操作系统文件描述符存在一对一的关系,以提供平台无关的操作特性。

NIO Channel 基础

Channel 的实现使用本地代码来执行实际工作。Channel 接口允许我们以可移植且受控的方式访问底层 I/O 服务。

在层级结构的顶部,Channel 接口如下所示

正如我们在上面的 Channel 接口中看到的,所有 Channel 都具有两个通用操作:

  • 检查 Channel 是否已关闭 (isclose())
  • 关闭 Channel (close())

选择器

在 Java NIO 中,Selector 是可选择 Channel 的多路复用器,它用作一种特殊的 Channel,可以设置为非阻塞模式。它可以检查一个或多个 NIO Channel,并确定哪个 Channel 已准备好进行通信,即读取或写入。

Selector 的作用是什么

Selector 用于使用单个线程处理多个 Channel。因此,处理 Channel 所需的线程更少。

在线程之间切换对操作系统来说开销很大。因此,为了提高系统效率,可以使用 Selector。

让我们看看一个使用 Selector 来处理 3 个 Channel 的线程的说明

Java Nio tutorial8

创建 Selector

我们可以通过调用 Selector.open() 方法来创建一个 Selector,如下所示:

下一个主题Java NIO Channels