08【AIO编程】

article/2025/9/13 20:13:39

八、AIO编程

8.1 AIO编程简介

8.1.1 AIO编程概述

AIO也叫异步非阻塞,JDK1.7之后的新特性,AIO引入异步通道的概念,采用了 Proactor 模式,简化了程序编写,有效的请求才启动线程,它的特点是先由操作系统完成后才通知服务端程序启动线程去处理,一般适用于连接数较多且连接时间较长的应用。

与NIO模型不同,读写操作为例,只需直接调用read和write的API即可,这方法都是异步的对于读操作,当有流可读时,系统会将可读的流传入到read方法的缓冲区,并通知应用程序读写都是异步的,完成之后会主动调用回调函数;

AIO需要操作系统的支持,在Linux内核2.6版本之后增加了对真正异步IO的实现。Java从JDK1.7之后支持AIO,JDK1.7新增一些与文件/网络IO相关的一些API,称之为NIO2.0或者称之为AIO(Asynchronous IO)。AIO最大的特征提供了异步功能,对于socket网络通信和文件IO都是起作用的。

8.1.2 AIO与其他IO的区别

AIO是异步非阻塞IO,AIO实现了真正意义上的异步处理。

  • 异步:当在处理一个请求的同时,还可以同时处理其他请求,并且当请求处理完毕时(开始响应数据),基于事件回调的方式将数据响应给调用者,调用者不需要再次来到提供者这边读取数据,而是直接读取调用者中用户空间中的数据,完完全全的做到了异步处理;
  • 非阻塞:在AIO中,调用任何的请求连接、读取提供者数据等方法都不会造成当前线程阻塞,而是将请求告诉给了服务提供者,自己可以去处理其他任务;服务提供者接收到请求后,实现自身的业务逻辑处理,然后将数据数据发送给调用者;

BIO(同步阻塞):

在这里插入图片描述

NIO(同步非阻塞):

在这里插入图片描述

AIO(同步非阻塞):

在这里插入图片描述


  • BIO同步阻塞:到理发店理发,理发店人多,就一直等理发师,知道轮到自己理发

  • NIO同步非阻塞:到理发店理发,发现理发店人很多,就先告诉理发师说一会再来,自己先去干其它事情,一会再回来看看是否轮到了自己

  • AIO异步非阻塞:给理发师打电话,让理发师上门服务,自己干其它事情,理发师自己来家里理发

8.2 实现AIO编程

在Java中,实现AIO编程的主要有AsynchronousFileChannel、AsynchronousServerSocketChannel、AsynchronousSocketChannel等三个异步通道类;使用read、accept等阻塞方法时,异步通道则是基于事件回调的方式来处理阻塞问题;

即:当调用阻塞方法时不再阻塞当前线程,并且当数据提供者响应数据时将,数据请求方将会自动将操作系统内核所获取到的数据复制到用户空间,供用户提供者使用;

8.2.1 AIO基于文件编程

1)基于Future-读

  • 示例代码:
package com.aio.demo01_asynchronousFileChannel;import java.nio.ByteBuffer;
import java.nio.channels.AsynchronousFileChannel;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;
import java.util.concurrent.Future;/*** @author lscl* @version 1.0* @intro:*/
public class Demo01_通过Future读取数据 {public static void main(String[] args) throws Exception {Path path = Paths.get("001.txt");// 创建一个异步的FileChannel对象,设置为读模式AsynchronousFileChannel fileChannel =AsynchronousFileChannel.open(path, StandardOpenOption.READ);// 创建Buffer来接收AsynchronousFileChannel的数据ByteBuffer buffer = ByteBuffer.allocate(1024);// 进行异步读取Future<Integer> future = fileChannel.read(buffer, 0);/*如果isDone()返回true,代表内核空间已经准备好了数据,并且已经将内核的数据拷贝到用户空间了返回false,则代表内核空间暂时没有数据,或者数据还没有从内核拷贝到用户空间*/while (!future.isDone()) ;// limit=position,position=0buffer.flip();System.out.println(new String(buffer.array()));// position=0,limit=capacitybuffer.clear();// 可以获取到读取的字节数Integer count = future.get();System.out.println("读取完毕,共读取到【" + count + "】个字节");}
}

2)基于CompletionHandler-读

  • 示例代码:
package com.aio.demo01_asynchronousFileChannel;import java.nio.ByteBuffer;
import java.nio.channels.AsynchronousFileChannel;
import java.nio.channels.CompletionHandler;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;/*** @author lscl* @version 1.0* @intro:*/
public class Demo02_通过CompletionHandler读取数据 {public static void main(String[] args) throws Exception {Path path = Paths.get("001.txt");// 创建一个异步的FileChannel对象,设置为读模式AsynchronousFileChannel fileChannel =AsynchronousFileChannel.open(path, StandardOpenOption.READ);ByteBuffer buffer = ByteBuffer.allocate(1024);// 进行异步读取fileChannel.read(buffer, 0, buffer, new CompletionHandler<Integer, ByteBuffer>() {/*** 读取完毕时调用的方法* @param result: 读取的字节数量* @param attachment: 附着的信息,该参数等于fileChannel调用read时传递的buffer(第三个参数的buffer)*/@Overridepublic void completed(Integer result, ByteBuffer attachment) {// trueSystem.out.println(buffer == attachment);// limit=position,position=0buffer.flip();System.out.println(new String(buffer.array()));// position=0,limit=capacitybuffer.clear();}/*** 读取失败时调用的方法* @param exc: 出现的异常* @param attachment: 外面传递的那个buffer对象*/@Overridepublic void failed(Throwable exc, ByteBuffer attachment) {exc.printStackTrace();}});System.out.println("程序执行完毕...");}
}

3)基于Future-写

  • 示例代码:
package com.aio.demo01_asynchronousFileChannel;import java.nio.ByteBuffer;
import java.nio.channels.AsynchronousFileChannel;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;
import java.util.concurrent.Future;/*** @author lscl* @version 1.0* @intro:*/
public class Demo03_通过Future写取数据 {public static void main(String[] args) throws Exception {Path path = Paths.get("001.txt");// 创建一个AsynchronousFileChannel,对与该类来说,每次运行不会清空文件,而是每次运行都会把本次的内容覆盖文件之前的内容AsynchronousFileChannel fileChannel =AsynchronousFileChannel.open(path,StandardOpenOption.WRITE,StandardOpenOption.TRUNCATE_EXISTING       // 如果文件里面有内容那么就清空数据);ByteBuffer buffer = ByteBuffer.wrap("abc".getBytes());Future<Integer> future = fileChannel.write(buffer, 0);System.out.println("写出【" + future.get() + "】个字节");fileChannel.close();}
}

4)基于CompletionHandler-写

  • 示例代码:
package com.aio.demo01_asynchronousFileChannel;import java.nio.ByteBuffer;
import java.nio.channels.AsynchronousFileChannel;
import java.nio.channels.CompletionHandler;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;/*** @author lscl* @version 1.0* @intro:*/
public class Demo04_通过CompletionHandler写取数据 {public static void main(String[] args) throws Exception {Path path = Paths.get("001.txt");// 创建一个AsynchronousFileChannel,对与该类来说,每次运行不会清空文件,而是每次运行都会把本次的内容覆盖文件之前的内容AsynchronousFileChannel fileChannel =AsynchronousFileChannel.open(path,StandardOpenOption.WRITE,StandardOpenOption.TRUNCATE_EXISTING            // 如果文件里面有内容那么就清空数据);ByteBuffer buffer = ByteBuffer.wrap("abc".getBytes());fileChannel.write(buffer, 0, null, new CompletionHandler<Integer, ByteBuffer>() {@Overridepublic void completed(Integer result, ByteBuffer attachment) {System.out.println("写出【" + result + "】个字节");}@Overridepublic void failed(Throwable exc, ByteBuffer attachment) {exc.printStackTrace();}});System.out.println("写入完毕....");// 让程序不要这么快结束(等待completed回调函数执行)Thread.sleep(100);}
}

8.2.2 AIO基于网络编程

1)服务端

  • 示例代码:
package com.aio.demo01_asynchronousFileChannel;import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.AsynchronousServerSocketChannel;
import java.nio.channels.AsynchronousSocketChannel;
import java.nio.channels.CompletionHandler;/*** @author lscl* @version 1.0* @intro:*/
public class Demo05_基于服务器的AIO通信模式_服务端 {public static void main(String[] args) throws Exception {// 创建一个异步的ServerSocketChannelAsynchronousServerSocketChannel serverSocketChannel = AsynchronousServerSocketChannel.open();// 绑定IP和端口serverSocketChannel.bind(new InetSocketAddress("127.0.0.1", 8888));/*接收一个客户端该方法不会阻塞当前线程,而是基于事件回调的形式,当接收到客户端时执行回调函数把接收到的客户端传递进去*/serverSocketChannel.accept(null, new CompletionHandler<AsynchronousSocketChannel, Object>() {/*** 接收成功执行的回调* @param socketChannel: 客户的Channel* @param attachment: 添加的附着信息*/@Overridepublic void completed(AsynchronousSocketChannel socketChannel, Object attachment) {ByteBuffer buffer = ByteBuffer.allocate(1024);/*使用AsynchronousSocketChannel进行读取该方法并不会阻塞当前线程,而是基于事件回调的形式,当客户端有数据可读时,触发回调函数*/socketChannel.read(buffer, null, new CompletionHandler<>() {@Overridepublic void completed(Integer result, Object attachment) {// limit=position,position=0buffer.flip();try {System.out.println("接收到了来自客户端【" + socketChannel.getRemoteAddress() + "】发送的信息: " + new String(buffer.array()));} catch (IOException exception) {exception.printStackTrace();}// position=0,limit=capacitybuffer.clear();}@Overridepublic void failed(Throwable exc, Object attachment) {}});}/*** 接收失败的回调* @param exc* @param attachment*/@Overridepublic void failed(Throwable exc, Object attachment) {exc.printStackTrace();}});// 让程序不会结束System.in.read();}
}

2)客户端

  • 示例代码:
package com.aio.demo01_asynchronousFileChannel;import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.AsynchronousSocketChannel;
import java.nio.channels.CompletionHandler;/*** @author lscl* @version 1.0* @intro:*/
public class Demo06_基于服务器的AIO通信模式_客户端 {public static void main(String[] args) throws Exception {// 获取一个异步的SocketChannelAsynchronousSocketChannel socketChannel = AsynchronousSocketChannel.open();/*连接到服务器该方法不会阻塞,*/socketChannel.connect(new InetSocketAddress("127.0.0.1", 8888), null, new CompletionHandler<Void, Object>() {/*** 连接服务器成功执行的方法* @param result* @param attachment*/@Overridepublic void completed(Void result, Object attachment) {ByteBuffer buffer = ByteBuffer.allocate(1024);buffer.put("hello".getBytes());// limit=position,position=0buffer.flip();// 将数据发送到服务器socketChannel.write(buffer);// position=0,limit=capacitybuffer.clear();}@Overridepublic void failed(Throwable exc, Object attachment) {}});// 让程序不会结束System.in.read();}
}

http://chatgpt.dhexx.cn/article/ZXWPQEfT.shtml

相关文章

linux aio进程简介,Linux AIO机制

Linux的I/O机制经历了一下几个阶段的演进&#xff1a; 1. 同步阻塞I/O: 用户进程进行I/O操作&#xff0c;一直阻塞到I/O操作完成为止。 2. 同步非阻塞I/O: 用户程序可以通过设置文件描述符的属性O_NONBLOCK&#xff0c;I/O操作可以立即返回&#xff0c;但是并不保证I/O操作成功…

关于aio

AIO 是异步非阻塞 同步意味着&#xff0c;在进行读写操作时&#xff0c;线程需要等待结果&#xff0c;还是相当于闲置 异步意味着&#xff0c;在进行读写操作时&#xff0c;线程不必等待结果&#xff0c;而是将来由操作系统来通过回调方式由另外的线程来获得结果 AIO的read方…

linux AIO

AIO 是 Linux 下的异步读写模型&#xff0c;它是 2.6 内核提供的一个标准增强特性。对于文件的读写&#xff0c;即使以 O_NONBLOCK 方式来打开一个文件&#xff0c;也会处于 “阻塞” 状态&#xff0c;因为文件时时刻刻处于可读状态&#xff0c;而从磁盘到内存所等待的时间是惊…

AIO模型

目录 AIO模型介绍 AsynchronousServerSocketChannel&#xff1a;AIO中网络通信服务端的socket 1、future方法 2、callback回调方式 AIO 的回调方式编程 BIO、NIO、AIO的比较 1、释义 BIO&#xff1a;同步阻塞IO模型 NIO&#xff1a;同步非阻塞IO模型 AIO&#xff1a;…

java中IO模型-AIO模型

AIO模型介绍 AIO&#xff08;Asynchronous I/O&#xff09; 异步非阻塞模型&#xff0c; 在javajdk.17版本开始支持AIO&#xff0c;AIO模型需要操作系统的支持。 AIO最大的特性是异步能力&#xff0c;对socket和I/O起作用。 异步IO模型类似的 与NIO模型不同&#xff0c;读写操…

架构解密从分布式到微服务:深入理解网络,AIO

AIO AIO是I/O模型里一个很高的层次&#xff0c;体现了大道至简的软件美学理念。与NIO相比&#xff0c;AIO的框架和使用方法相对简单很多。 AIO包括两大部分:AIO Files解决了文件的异步处理问题&#xff0c;AIO Sockets解决了Socket的异步处理问题。AIO的核心概念为应用发起非…

BIO,NIO,AIO区别

BIO,NIO,AIO 总结 Java 中的 BIO、NIO和 AIO 理解为是 Java 语言对操作系统的各种 IO 模型的封装。程序员在使用这些 API 的时候&#xff0c;不需要关心操作系统层面的知识&#xff0c;也不需要根据不同操作系统编写不同的代码。只需要使用Java的API就可以了。 在讲 BIO,NIO,…

Apache CXF - 快速指南

Apache CXF - 简介 在当今的环境中&#xff0c;您可以使用多个选项来创建 Web 服务应用程序。您可以使用多种标准和广泛接受的协议中的一种或多种进行通信。例如SOAP、XML/HTTP、RESTful HTTP和CORBA&#xff08;通用对象请求代理架构&#xff0c;在过去非常流行&#xff0c;但…

java cxf 安全_CXF client在并发下的线程安全问题

这个是发生在上周周末的真实案例&#xff0c;因为cxf client 端线程安全导致的错误&#xff0c;总结出来希望其他使用cxf的兄弟注意。 首先描述一下背景&#xff0c;简单的说就是使用cxf作为web service的客户端&#xff0c;运行在weblogic上&#xff0c;连接外部的服务器。为了…

linux cxf服务端,Apache CXF 框架应用实战

一、概述 Apache CXF提供了用于方便地构建和开发WebService的可靠基础架构。它允许创建高性能和可扩展的服务&#xff0c;可以部署在Tomcat和基于Spring的轻量级容器中&#xff0c;也可以部署在更高级的服务器上&#xff0c;例如Jboss、WebSphere或WebLogic。 CXF提供了以下功能…

使用CXF调用WSDL

简介 时隔多年&#xff0c;再次遇到需要调用WebService的业务&#xff0c;对方给予的wsdl说明文档还是内网的链接&#xff0c;并且设有基础访问权限&#xff0c;即在浏览器打开wsdl链接时需要输入【用户名密码】登录后方可查看wsdl文档&#xff0c;这需要设置代理&#xff08;我…

spring5.x cxf3.4.x 服务端和客户端 非maven版本

文章目录 一、资料准备1. 官网链接2. 解压3. 依赖梳理 二、spring集成cxf2.1.创建spring项目2.2. 创建接口2.3. impl2.4. spring-cxf.xml2.5. 客户端2.6. 开源项目 一、资料准备 1. 官网链接 http://cxf.apache.org/download.html 下载apache-cxf-3.4.5.zip 2. 解压 3. 依赖…

CXF实现WebService

一、CXF简介 Apache CXF Celtix XFire&#xff0c;开始叫 Apache CeltiXfire&#xff0c;后来更名为 Apache CXF 了&#xff0c;以下简称为 CXF。CXF 继承了 Celtix 和 XFire 两大开源项目的精华&#xff0c;提供了对 JAX-WS 全面的支持&#xff0c;并且提供了多种 Binding …

SpringBoot2 整合 CXF 服务端和客户端

文章目录 一、CXF服务端1. 导入依赖2. 创建service接口3. 接口实现类4. cxf配置类5. 查看wsdl结果 二、CXF客户端2.1. 客户端2.2. 断点调试2.3. 发起调用服务开源源码. 一、CXF服务端 1. 导入依赖 <properties><cxf.version>3.3.1</cxf.version></proper…

CXF客户端乱码

CXF客户端乱码 解决办法一&#xff0c;设置服务端代码&#xff1a; 在使用CXF与其他系统对接时&#xff0c;发现对方系统响应的汉字乱码&#xff0c;使用soapui调用测试就没有问题&#xff0c;但是程序里面调用就乱码&#xff0c;很奇怪&#xff0c;乱码如下&#xff1a; 由…

SpringBoot集成CXF

CXF入门篇https://blog.csdn.net/tongxin_tongmeng/article/details/126482362Server端项目结构 Server端pom.xml <project xmlns"http://maven.apache.org/POM/4.0.0" xmlns:xsi"http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation"…

走进cxf

一、什么是cxf 有很多人认为cxf就是webservice&#xff0c;其实cxf只是发布调用webservice的工具而已 Apache CXF Celtix Xfire&#xff0c;开始叫 Apache CeltiXfire&#xff0c;后来更名为 Apache CXF 了&#xff0c;以下简称为 CXF。Apache CXF 是一个开源的 web Service…

NewSQL ---- Mysql.8.0 与 MemSQL 7.0 大数据量查询性能对比

目录 1测试环境以及测试用例设计 1.1测试环境 1.2测试用例设计 2 千万级数据量性能测试对比 2.1 MemSQL时间范围分页查询 2.1.1 性能测试数据 2.2任务信息查询 2.2.1 性能测试数据 2.3 执行批次范围查询 2.3.1 性能测试数据 2.4 批次任务查询 2.4.1 性能测试数据 …

memsql架构2

接上次的MemSQL分布式架构介绍(一)&#xff0c;原文在这里&#xff1a;http://docs.memsql.com/latest/concepts/distributed_architecture/ 首先上张图&#xff0c;是我根据自己的理解画的&#xff0c;如有错误还请大家指出 几个概念 1、MemSQL有两种类型的表&#xff1a; ref…

MemSQL性能测试结果

1.查询的SQL select count(subie.user_id) as count from sum_user_basic_info_exp subie join sum_user_lend_info_exp sulie on sulie.user_idsubie.user_id where subie.curr_user_role_cd1 and subie.reg_dt >2016-08-29 and subie.reg_dt <2016-08-29 结…