Java NIOAIO

多路复用概念介绍

多路复用是一个在计算机网络、操作系统,以及软件开发中广泛使用的技术,它允许单一的资源(如网络连接或者CPU)同时服务于多个请求或多个应用程序。在I/O操作(输入/输出操作)的上下文中,多路复用通常指的是使用单一的线程或少量线程来同时处理多个I/O请求。

多路复用的主要形式

  1. I/O多路复用(在网络编程中常见)

    • 使用单一的线程监听多个网络连接,处理所有的输入和输出请求。这通常涉及到监听哪些连接上有数据可以读取,或者哪些连接准备好可以写入数据而不会被阻塞。
    • 常见的实现技术包括使用select, poll, 或 epoll(在Linux系统中)。
  2. 异步I/O(AIO)

    • 异步I/O模型允许应用程序启动一个或多个I/O操作,然后继续执行其他任务,无需等待这些操作完成。当I/O操作实际完成时,应用程序将接收到通知。
    • 在Java中,这通过使用AsynchronousFileChannelAsynchronousSocketChannel等类实现。

多路复用与阻塞/非阻塞I/O的关系

  • 阻塞I/O:在这种模型下,应用程序发起一个I/O操作后,必须等待操作完成才能继续执行。在等待期间,应用程序的线程被挂起。
  • 非阻塞I/O:在非阻塞模式下,I/O调用将立即返回一个状态,告诉应用程序数据是否可用。如果数据未就绪,应用程序可以做其他事情,而不是等待,从而提高了应用程序的效率。

Java NIO中的多路复用

Java的NIO库提供了基于通道(Channel)和缓冲区(Buffer)的I/O操作,以及一个选择器(Selector)机制,用于非阻塞的多路复用I/O操作。通过使用选择器,一个单独的线程可以监控多个输入源的数据状态,实现多路复用:

  • 选择器(Selector):一个可以监控一组通道的对象,用来检查哪一个或哪几个通道已经准备好进行读取或写入。
  • 通道(Channel):类似于传统的流,但它们可以被设置为非阻塞模式。在非阻塞模式下,应用程序可以请求读写操作,并且立即得到返回,不需要等待操作实际完成。

通过选择器,一个线程可以有效地管理多个通道的I/O操作,这样即使在处理大量连接时也不需要为每个连接创建一个线程,从而大幅度降低资源消耗和提高效率。这种模型非常适合需要处理大量并发连接的服务器,例如Web服务器或应用服务器。

Java NIO&AIO简介

Java NIO(New Input/Output)和 AIO(Asynchronous Input/Output)都是Java平台上处理非阻塞I/O的技术,但它们在处理I/O操作的方式和实现机制上有着显著的差异。以下是NIO和AIO之间的主要区别:

1. 操作模式

  • NIO 是基于事件驱动的非阻塞I/O模型。它使用**选择器(Selectors)通道(Channels)**的概念,通过一个线程来监控多个输入通道,看是否有数据准备好可以被读取或写入。当数据准备好时,系统将通知应用程序,应用程序再进行实际的读写操作。
  • AIO 是真正的异步I/O,它不需要周期性地检查数据是否可用。AIO引入了异步通道的概念,允许应用程序直接进行读写操作,并在操作完成后通过回调函数或者Future对象处理结果。

2. 性能和资源利用

  • NIO 虽然是非阻塞的,但在处理大量连接时可能需要频繁地检查所有连接的状态,这种模型可能导致资源的浪费(尽管相比于传统的阻塞IO已经大幅改进)。
  • AIO 提供了更高的性能和更好的资源利用率,在处理成千上万的并发连接时表现更优,因为它通过操作系统的直接支持来异步处理I/O操作,减少了不必要的CPU消耗。

3. 应用场景

  • NIO 适合于连接数目较多但每个连接上的数据传输量不是特别大的场景,如网络服务器。
  • AIO 更适合于高负载、高并发的应用场景,特别是在I/O操作非常耗时的情况下(如大文件传输),能够有效地提升性能。

4. API复杂度

  • NIO 的API相对复杂,需要管理缓冲区、选择键(SelectionKey)等,同时还需要处理线程安全和数据同步等问题。
  • AIO 的API设计更为简洁直观,使用起来更加方便,特别是在进行复杂的异步操作时,可以使代码更加清晰。

5. 支持和可用性

  • NIO 从Java 1.4开始引入,而完整的NIO.2(包括对文件系统的改进)是在Java 7中引入的。
  • AIO 是在Java 7中引入的,是Java平台对真异步I/O的支持。

总之,选择NIO还是AIO主要取决于具体的应用需求和预期的系统负载。对于需要处理大量并发连接且每个连接上的数据量不是很大的应用,NIO可能是一个更好的选择。而对于那些I/O操作非常耗时且需要高效率处理的应用,AIO可能更合适。

NIO编程

在Java中使用NIO(非阻塞IO)通常涉及到使用通道(Channels)和缓冲区(Buffers)来进行I/O操作,以及选择器(Selectors)来管理多个通道。这里将通过一个简单的服务器示例,来展示如何在Java中实现基于NIO的编程实践。

NIO编程关键组件

  1. 通道 (Channel):类似于流,但主要区别在于通道是双向的,可以读也可以写。最常用的是SocketChannelServerSocketChannel
  2. 缓冲区 (Buffer):数据的容器。数据从通道读入缓冲区,从缓冲区写入通道。例如ByteBuffer
  3. 选择器 (Selector):可以监视多个通道的IO状况,是单线程管理多个连接实现非阻塞IO的关键。

示例:基于NIO的Echo服务器

以下是一个简单的Echo服务器实现,该服务器会将客户端发送的消息原样返回。

步骤1:设置服务器通道和选择器
import java.net.*;
import java.nio.*;
import java.nio.channels.*;
import java.nio.charset.StandardCharsets;
import java.util.*;public class EchoServer {public static void main(String[] args) throws Exception {// 创建选择器Selector selector = Selector.open();// 打开服务器Socket通道ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();serverSocketChannel.configureBlocking(false); // 设置为非阻塞模式serverSocketChannel.socket().bind(new InetSocketAddress(8080));serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);System.out.println("Server started on port 8080");while (true) {// 非阻塞模式,选择器每隔一定时间检查一次注册的通道if (selector.select() == 0) {continue;}// 获取所有接收事件的SelectionKey实例Set<SelectionKey> selectedKeys = selector.selectedKeys();Iterator<SelectionKey> iter = selectedKeys.iterator();while (iter.hasNext()) {SelectionKey key = iter.next();// 根据事件类型进行处理if (key.isAcceptable()) {// 接受客户端连接请求handleAccept(serverSocketChannel, selector);} else if (key.isReadable()) {// 读取数据handleRead(key);}iter.remove();}}}private static void handleAccept(ServerSocketChannel serverSocketChannel, Selector selector) throws Exception {SocketChannel clientChannel = serverSocketChannel.accept();clientChannel.configureBlocking(false);clientChannel.register(selector, SelectionKey.OP_READ);System.out.println("Accepted connection from " + clientChannel);}private static void handleRead(SelectionKey key) throws Exception {SocketChannel clientChannel = (SocketChannel) key.channel();ByteBuffer buffer = ByteBuffer.allocate(1024);int numRead = clientChannel.read(buffer);if (numRead == -1) {clientChannel.close();key.cancel();System.out.println("Connection closed by client");return;}// 回显数据buffer.flip();byte[] data = new byte[buffer.remaining()];buffer.get(data);System.out.println("Received: " + new String(data, StandardCharsets.UTF_8));// 将数据写回客户端clientChannel.write(ByteBuffer.wrap(data));}
}

解释

  • 服务器设置:服务器通道被设置为非阻塞并注册到选择器。关注的事件是OP_ACCEPT,表示服务器准备好接受新的客户端连接。
  • 事件循环:服务器在一个无限循环中运行,等待并处理事件(接受连接或读取数据)。
  • 处理连接和读取:当selector发现有新的客户端连接时,它会接受连接并将返回的SocketChannel设置为非阻塞,然后注册到选择器上,关注读事件。读事件触发时,数据被读入ByteBuffer,并简单地回显到客户端。

这个示例展示了使用Java NIO来创建一个简单的服务器的基本步骤。NIO编程比标准的IO编程更复杂,但它能更有效地处理成千上万的并发连接,尤其是在高负载环境下。

AIO编程

在Java中,AIO(异步IO)是通过Java NIO 2的扩展实现的,它在Java 7中被引入作为一种真正的异步非阻塞IO模型。AIO提供了一种机制,允许应用程序在I/O操作完成时接收通知,而无需持续检查或等待I/O操作的完成。这通过使用异步通道和完成处理器(或Future对象)实现。

AIO编程的关键组件

  1. 异步通道:这些是用于数据读写的通道,如AsynchronousSocketChannelAsynchronousServerSocketChannel
  2. 完成处理器:一个实现了特定回调方法的对象,当异步操作完成时被调用。
  3. Future对象:另一种处理异步操作结果的方式,可以用来查询操作是否完成,或阻塞等待操作完成。

示例:基于AIO的Echo服务器

这个示例将展示如何使用AIO来实现一个简单的Echo服务器,该服务器异步地接收客户端连接和数据,并将接收到的数据原样返回给客户端。

步骤1:创建服务器通道
 
import java.net.*;
import java.nio.*;
import java.nio.channels.*;
import java.util.concurrent.*;public class AsyncEchoServer {public static void main(String[] args) {try {// 打开异步服务器通道AsynchronousServerSocketChannel serverChannel = AsynchronousServerSocketChannel.open();serverChannel.bind(new InetSocketAddress(8080));System.out.println("Server is listening at " + 8080);serverChannel.accept(null, new CompletionHandler<AsynchronousSocketChannel, Void>() {@Overridepublic void completed(AsynchronousSocketChannel clientChannel, Void attachment) {// 一旦接受连接,再次准备接受新的连接serverChannel.accept(null, this);handleClient(clientChannel);}@Overridepublic void failed(Throwable exc, Void attachment) {System.out.println("Failed to accept new connection");exc.printStackTrace();}});// 服务器需要一直运行,使用CountDownLatch来阻塞new CountDownLatch(1).await();} catch (IOException | InterruptedException e) {e.printStackTrace();}}private static void handleClient(AsynchronousSocketChannel clientChannel) {ByteBuffer buffer = ByteBuffer.allocate(1024);clientChannel.read(buffer, buffer, new CompletionHandler<Integer, ByteBuffer>() {@Overridepublic void completed(Integer result, ByteBuffer attachment) {attachment.flip();clientChannel.write(attachment, attachment, new CompletionHandler<Integer, ByteBuffer>() {@Overridepublic void completed(Integer result, ByteBuffer buffer) {if (buffer.hasRemaining()) {buffer.compact();clientChannel.read(buffer, buffer, this);} else {try {clientChannel.close();} catch (IOException e) {e.printStackTrace();}}}@Overridepublic void failed(Throwable exc, ByteBuffer attachment) {System.out.println("Failed to write data to client");exc.printStackTrace();try {clientChannel.close();} catch (IOException e) {e.printStackTrace();}}});}@Overridepublic void failed(Throwable exc, ByteBuffer attachment) {System.out.println("Failed to read data from client");exc.printStackTrace();try {clientChannel.close();} catch (IOException e) {e.printStackTrace();}}});}
}

解释

  • 异步服务器通道:服务器使用AsynchronousServerSocketChannel来监听端口。这个通道被配置为异步模式,并绑定到指定端口。
  • 接受连接:使用accept方法开始异步接受新连接,连接到来时会调用CompletionHandlercompleted方法。
  • 处理客户端数据:在处理客户端连接时,同样使用异步读写操作,通过传递CompletionHandler来处理读写完成后的事件。

这个示例展示了AIO编程的一些基本模式,如使用异步通道和完成处理器。这种模式可以有效地处理大量并发连接,而不会造成线程阻塞,从而提高了应用程序的性能和响应能力。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/10216.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

什么是IP跳变?

IP 跳跃&#xff08;也称为 IP 跳动&#xff09;的概念已引起使用代理访问网站的用户的极大关注。但 IP 跳跃到底是什么&#xff1f;为什么它对于各种在线活动至关重要&#xff1f; 在本文中&#xff0c;我们将深入探讨 IP 跳跃的世界&#xff0c;探索其实际应用、用例、潜在问…

读写备份寄存器BKP与实时时钟RTC

文章目录 读写备份寄存器接线图代码 RTC实时时钟接线图代码 读写备份寄存器 接线图 即接个3.3v的电源到VBT引脚 代码 代码效果&#xff1a;第一次写入备份寄存器&#xff0c;下载程序后再注释掉&#xff0c;再进行下载&#xff0c;之前写入的数据还会保存在备份寄存器中&am…

使用 sudo apt upgrade 出现的提示

┌────────────────────────────────────────────────┤ Pending kernel upgrade ├────────────────────────────────────────────────┐ │ …

搭建一个vue3+vant4+vite4+pinia 的移动端h5模板

效果图 项目的创建和组件库的安装 项目创建 pnpm create vite vue3-vant4-vite-pinia-pro-h5注意&#xff1a; node版本控制在 18&#xff0c; 可以通过nvm来管理本地的node版本&#xff0c;具体可以看这篇文章 nvm的简单使用 vant-ui库的安装【这里安装的是 ^4.6.0 版本的】…

Maven- Profile详解

前言 Profile能让你为一个特殊的环境自定义一个特殊的构建&#xff1b;profile使得不同环境间构建的可移植性成为可能。 <project><profiles><profile><build><defaultGoal>...</defaultGoal><finalName>...</finalName><…

HTML控件和Web控件之间的区别是什么

HTML控件和Web控件在ASP.NET中有着不同的定义和用途&#xff0c;它们之间的主要区别体现在以下几个方面&#xff1a; 概念&#xff1a; HTML控件&#xff1a;就是我们通常所说的HTML语言标记&#xff0c;这些标记在静态页面和其他网页中存在。它们不能在服务器端直接控制&#…

linux系统服务器中常见故障及排查方法

目录 故障1&#xff1a;系统无响应 故障2&#xff1a;网络连接问题 故障3&#xff1a;文件系统错误 故障4&#xff1a;软件包依赖问题 故障5&#xff1a;用户权限问题 故障6&#xff1a;服务无法正常工作 故障7&#xff1a;磁盘空间不足 故障8&#xff1a;内存不足 故障…

2024年华为OD机试真题- 手机App防沉迷系统-(C++)-OD统一考试(C卷D卷)

题目描述: 智能手机方便了我们生活的同时,也侵占了我们不少的时间。“手机App防沉迷系统”能够让我们每天合理的规划手机App使用时间,在正确的时间做正确的事。 它的大概原理是这样的: 1、在一天24小时内,可注册每个App的允许使用时段; 2、一个时段只能使用一个App,举例…

掼蛋—开牌三步走

掼蛋是消遣也是一项脑力活动&#xff0c;除了牌运&#xff0c;还要掌握技巧。和大家一起分享一下掼蛋游戏中的“开牌三步走”技巧。 1、快速理牌 目的&#xff1a;潜力最大化 开局时可以快速查看一下自己的同花顺&#xff0c;优先保留不损害其他炸弹的同花顺&#xff0c;并及时…

精益生产咨询公司:深入探讨其独特魅力与核心竞争力

精益生产咨询公司&#xff0c;作为专注于帮助企业实现精益转型和效率提升的专业机构&#xff0c;在现代工业生产中扮演着不可或缺的角色。这些公司不仅具备深厚的行业经验和专业知识&#xff0c;还能够根据企业的实际情况和需求&#xff0c;提供个性化的解决方案和持续的支持服…

用户至上!探索7种常用的用户体验研究方法

用户体验研究是产品开放过程中的重要组成部分&#xff0c;优秀的产品设计与高质量的用户体验是不可分割的。对于产品开发&#xff0c;选择合适的用户体验研究方法在很大程度上决定了产品的使用效果。本文全面阐述了用户体验研究、用户体验研究的重要性和用户体验研究方法&#…

mamba复现—mamba+yolov8魔改(win)

Mamba复现出现的问题 安装下列步骤一步步走 一、 注&#xff1a;若是Windows环境下python一定是3.10版本的&#xff0c;要不然trition无法安装 conda create -n mamba python3.10 conda activate mamba conda install cudatoolkit11.8 -c nvidia pip install torch2.1.1 t…

探索国外静态住宅代理:保护网络安全与隐私的利器

随着互联网的日益发展&#xff0c;网络安全和隐私保护成为越来越多用户关注的焦点。在这个信息爆炸的时代&#xff0c;如何确保网络活动的匿名性和安全性成为了我们必须面对的问题。国外静态住宅代理作为一种新兴的网络技术&#xff0c;为我们提供了有效的解决方案。 &#xf…

OSTEP Projects:KV

本文将介绍操作系统导论&#xff08;Operating Systems: Three Easy Pieces&#xff09;作者所开源的操作系统相关课程项目 的 KV 部分&#xff0c;包含个人的代码实现和设计思路。 思路 题目要求实现一个最简单的数据库&#xff0c;以支持数据的持久化。 每个操作由格式为 o…

目标检测——道路检测数据集

引言 亲爱的读者们&#xff0c;您是否在寻找某个特定的数据集&#xff0c;用于研究或项目实践&#xff1f;欢迎您在评论区留言&#xff0c;或者通过公众号私信告诉我&#xff0c;您想要的数据集的类型主题。小编会竭尽全力为您寻找&#xff0c;并在找到后第一时间与您分享。 …

C#中的异步编程模型

在C#中&#xff0c;async和await关键字是用于异步编程的重要部分&#xff0c;它们允许你以同步代码的方式编写异步代码&#xff0c;从而提高应用程序的响应性和吞吐量。这种异步编程模型在I/O密集型操作&#xff08;如文件读写、网络请求等&#xff09;中特别有用&#xff0c;因…

在Ubuntu上安装Anaconda并配置远程访问Jupyter

安装 下载Anaconda的.sh文件后&#xff0c;上传到服务器&#xff0c;然后进行安装&#xff1a; chmod x anaconda.sh ./anaconda.sh创建虚拟环境 可以指定Python版本创建虚拟环境&#xff1a; conda create --name langchain python3.11.7 conda activate langchain conda …

如何在Springboot项目的Mapper中增加一个新的sql语句

在做项目的过程中&#xff0c;我发现有的时候需要用到一些不在springboot的Mapper中的Sql语句&#xff0c;那么应该如何进行操作呐&#xff1f;&#xff1f; 平常我们创建springbootmybatisPlus项目的时候是这样创建的&#xff1a;&#xff1a; 1、创建实体类 2、创建Mappe…

【Python】如何训练模型并保存本地和加载模型

这个年纪的我们 爱情跟不上分开的节奏 这个年纪的我们 更珍惜难得的自由 这个年纪的我们 比起从前更容易感动 这个年纪的我们 徘徊在理想与现实之中 &#x1f3b5; 齐一《这个年纪》 逻辑回归是一种常用的分类算法&#xff0c;能够根据输入特征预测目标变…

https://blog.csdn.net/gang542725/article/details/138621192

uboot Ethernet 数据收发流程【1】 总结了一部分uboot收发数据的流程 这里继续 ! static int eqos_start(struct udevice *dev) 1210{ 1211 struct eqos_priv *eqos = dev_get_priv(dev); 1212 int ret, i; 1213 ulong rate; 1214 u32 val, tx_fifo_sz, rx_fifo_sz, tqs, …