Java NIO中的非阻塞服务器


非阻塞服务器

Java NIO(新输入/输出)是一个非常强大的网络和文件处理应用程序,可以用作 Java 标准 IO API 的替代方案。由于自 JDK 4 引入以来添加了更多高级功能,它已迅速成为众多工程师的首选 I/O 系统。

它提供改进的文件处理和文件系统功能支持是其区别于其他功能之一。由于 NIO 文件类具有如此强大的功能,因此它被广泛用于文件处理。

仔细观察,您会注意到 java.nio 包指定了 NIO API 始终使用的缓冲区类。最棒的是,它是为了让 Java 程序员能够实现快速 I/O 而无需编写其本机代码而创建的。

阻塞与非阻塞 I/O

由于使用了非阻塞 I/O,非阻塞服务器可以通过同一个进程或线程同时处理多个请求。将阻塞进程视为售票处排队,其中每个客户都必须等待前面的人员服务完毕才能继续。

相反,非阻塞进程就像餐厅的服务员,试图通过轮流为所有顾客服务并处理他们的订单来同时为所有顾客服务。

阻塞服务器以同步方式工作,并在继续下一个请求之前完成每个请求。这可能导致客户端等待时间更长,并且需要多个线程来服务每个请求,从而使其成为 CPU 密集型操作。另一方面,非阻塞服务器使用异步方法,允许一个线程同时处理多个查询,并在每个请求完成后做出响应。

Java NIO 的功能

Java NIO 有一些独特的特性,使其有别于其他 IO 系统。以下是 Java NIO 主要功能的概述:

  • 异步和非阻塞 IO − 此功能允许线程在数据读取到缓冲区时执行其他任务。线程无需等待数据完全加载才能开始处理,而可以在读取数据时继续其工作。

  • 面向缓冲区的方法 − Java NIO 将数据存储在缓冲区中,这允许快速访问和处理。当需要数据时,它将从缓冲区中检索和处理。

算法

  • 步骤 1 − 首先,我们必须使用 import 语句导入必要的类。

  • 步骤 2 − 接下来,我们需要创建一个名为“WriteExample2”的公共类。

  • 步骤 3 − 在此类中,我们必须定义一个接受 String 类型变量参数的公共静态 void main 函数。

  • 步骤 4 − 现在,使用 Files.createTempFile() 方法创建一个扩展名为“.txt”的临时文件。要写入,我们可以使用 Files.write() 方法以及保存字符串“Hello”和“world”的可迭代对象。

  • 步骤 5 − 要读取 Files' createTempFile() 函数返回的 Path 对象定义的文件中的每个字节,我们可以使用 Files.readAllBytes() 函数。之后,我们需要使用新的 String() 构造函数将其转换为字符串。

  • 步骤 6 − 最后,使用 System.out.println() 方法将字符串打印到控制台。

示例 1

此 Java 代码创建一个临时文本文件,并将“Hello”和“world”写入其中。然后读取文件并打印其内容。该代码使用 Java NIO 包中的 Files 类来处理文件操作。

package com.tutorialspoint.example.files;

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Arrays;

public class WriteExample2 {
   public static void main(String... args) throws IOException {
      Path path = Files.createTempFile("test-file", ".txt");
      Iterable<String> iterable = Arrays.asList("Hello", "world");
      Files.write(path, iterable);
      byte[] bytes = Files.readAllBytes(path);
      System.out.println(new String(bytes));
   }
}

输出

Hello
world

Java NIO 的组件

Java NIO 建立在三个基本组件之上:缓冲区、通道和选择器。以下是每个组件的简要概述:

  • 缓冲区 − 缓冲区是一块内存块,用于在数据从一个位置传输到另一个位置时临时存储数据。在 Java NIO 中,缓冲区用于促进数据的读取和写入。

  • 通道 − Java NIO 中的通道表示与可以执行 IO 操作的对象的连接,例如文件和套接字。通道负责在缓冲区与其表示的对象之间传输数据。

  • 选择器 − 选择器是 Java NIO 组件,用于监视一个或多个通道的事件,例如准备好执行 I/O 操作。当通道准备就绪时,选择器可以唤醒并允许相应的线程处理该操作。

非阻塞服务器组成

非阻塞服务器由非阻塞 IO 管道组成,该管道是一系列组件,以非阻塞方式处理读写 IO 操作。以下是此管道的工作原理:

  • 管道中的每个组件都使用选择器来确定通道是否有数据要读取。

  • 如果有数据,组件会读取它并根据它提供输出。之后,输出将写回通道。

  • 根据组件的不同,非阻塞 IO 管道可以读取和写入数据,以及执行这两种操作。

  • 组件通过选择器开始从通道读取数据。Java NIO 管理非阻塞 IO 操作,而选择器和选择键与可选择通道一起定义多路复用 IO 操作。

  • 非阻塞 IO 管道将数据划分为逻辑上排序或组合的消息以及非阻塞数据处理。这类似于使用 Java 的 StreamTokenizer 类对数据流进行标记,然后再进行处理。

  • 与阻塞 IO 管道(使用类似于 InputStream 的接口并且一次只允许读取一个字节)不同,非阻塞模型使用 Java NIO 选择器来检查并仅提供确实有数据要读取的 SelectableChannel 实例。

服务器读写操作的阻塞和非阻塞模型比较

在服务器架构的世界中,选择使用阻塞或非阻塞模型进行读写操作会极大地影响服务器的效率和可扩展性。

与阻塞模型相反,非阻塞模型允许进程通过交错非阻塞 I/O 调用来适应多个并发请求。

为了说明这些模型之间的区别,让我们考虑一个假设的服务器,该服务器接收两个请求。在阻塞模型中,进程必须等待请求 A 完全处理完毕才能继续处理请求 B。相反,非阻塞模型可以通过交错处理请求 A 和 B 来同时处理这两个请求。

Java NIO 使单个线程能够控制多个通道,从而支持非阻塞 I/O。

连接缓冲区和另一端对象的通道使异步数据传输成为可能。SocketChannel 和 ServerSocketChannel 两个类实现了 Java NIO 通道,并使通过 TCP 连接接收和写入数据成为可能。

服务器架构师可以通过选择合适的 I/O 模型来创建高效、可扩展的系统,并且能够管理大量并发请求。

结论

Java NIO 提供了一个强大的网络和文件处理应用程序,并改进了对文件处理和文件系统功能的支持。其异步和非阻塞 I/O、面向缓冲区的方法以及缓冲区、通道和选择器三个基本组件使其成为一个独特的 I/O 系统。

Java NIO 的非阻塞服务器模型能够通过使用非阻塞 I/O 管道同时处理多个请求。与阻塞 IO 管道不同,非阻塞模型检查并仅提供确实有数据要读取的 SelectableChannel 实例,使其成为更快、更高效的系统。

更新于: 2023年5月15日

771 次浏览

开启你的职业生涯

通过完成课程获得认证

开始学习
广告