Java NIO 中的非阻塞服务器
非阻塞服务器
Java NIO(新输入/输出)是一种非常强大的网络和文件处理应用程序,可作为 Java 标准 IO API 的替代方案。由于自 JDK 4 推出以来增加了更多复杂功能,它迅速成为众多工程师的首选 I/O 系统。
它对文件处理和文件系统功能提供的改进支持是区分 Java NIO 的功能之一。由于 NIO 文件类具有如此令人难以置信的功能,因此它被广泛用于文件处理。
如果仔细观察,您会注意到 java.nio 包指定了 NIO API 始终使用的缓冲区类。最好的方面是,它被创建是为了让 Java 程序员无需编写本机代码即可实现快速 I/O。
阻塞与非阻塞 I/O
由于使用非阻塞 I/O,非阻塞服务器可以通过同一进程或线程同时处理多个请求。阻塞进程就像售票柜台的队列,其中每个客户都必须等待前面的人得到服务才能继续。
相比之下,非阻塞进程就像餐厅的服务员,他试图通过轮流服务所有客户并处理他们的订单来同时为他们服务。
阻塞服务器以同步方式工作,在转到下一个请求之前完成每个请求。这可能会导致客户端等待时间更长,并且需要多个线程来处理每个请求,从而占用大量 CPU。另一方面,非阻塞服务器使用异步方法,允许一个线程同时处理多个查询,并在每个请求完成后对其做出反应。
Java NIO 的功能
Java NIO 具有一些独特的特性,使其有别于其他 IO 系统。以下是 Java NIO 主要功能的概述 -
A同步和非阻塞 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() 函数。之后,我们需要使用 new 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 类在处理数据流之前对其进行标记类似。
非阻塞模型使用 Java NIO 选择器来检查并仅提供具有要读取数据的 SelectableChannel 实例,而不是阻塞 IO 管道,后者使用类似于 InputStream 的接口,并且一次只允许读取一个字节。
服务器读/写操作的阻塞和非阻塞模型比较
在服务器架构领域,选择使用阻塞或非阻塞模型进行读写操作会极大地影响服务器的效率和可扩展性。
与阻塞模型相反,非阻塞模型允许进程通过交错非阻塞 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 实例,从而使其成为更快、更高效的系统。