简介
- 概念:异步IO模型(Asynchronous IO)简称AIO,其基本流程时:用户线程通过系统调用,向内核注册某个IO操作。内核在整个IO操作(包括数据准备、数据复制)完成后,通知用户程序,执行后续的业务操作。在异步IO模型中,整个内核的数据处理过程中,包括内核将数据从网络物理设备(网卡)读取到内核缓存区、将内核缓冲区的数据复制到用户缓冲区,用户程序都不需要阻塞。
- 理解:女友不想逛街,回家好好休息一下。于是我们叫外卖,打个电话点餐,然后我和女友可以在家好好休息一下,饭好了送货员送到家里来。这就是典型的异步,
过程
特点
- 优点:在内核等待数据和复制数据的两个阶段,用户线程都不是阻塞的。
- 缺点:需要操作系统底层内核提供支持,CPU开销太大。
应用
简单实现
- 服务器
public class MyAIOServer {
public static void main(String[] args) {
AsynchronousServerSocketChannel serverSocketChannel = null;
try {
serverSocketChannel = AsynchronousServerSocketChannel.open();
serverSocketChannel.bind(new InetSocketAddress(9999));
serverSocketChannel.accept(serverSocketChannel,new ServerHandler());
System.out.println("服务器已启动...");
CountDownLatch countDownLatch = new CountDownLatch(1);
countDownLatch.await();
} catch (IOException | InterruptedException e) {
e.printStackTrace();
}finally {
try {
if (serverSocketChannel != null){
serverSocketChannel.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
- ServerHandler
public class ServerHandler implements CompletionHandler<AsynchronousSocketChannel, AsynchronousServerSocketChannel> {
@Override
public void completed(AsynchronousSocketChannel result, AsynchronousServerSocketChannel attachment) {
attachment.accept(attachment, new ServerHandler());
doRead(result);
}
@Override
public void failed(Throwable exc, AsynchronousServerSocketChannel attachment) {
exc.printStackTrace();
}
private void doRead(AsynchronousSocketChannel channel) {
ByteBuffer byteBuffer = ByteBuffer.allocate(1024);
channel.read(byteBuffer, byteBuffer, new CompletionHandler<Integer, ByteBuffer>() {
@Override
public void completed(Integer result, ByteBuffer attachment) {
byteBuffer.flip();
System.out.println("客户端发送的数据为: "+new String(byteBuffer.array()));
doWrite(channel);
}
@Override
public void failed(Throwable exc, ByteBuffer attachment) {
exc.printStackTrace();
}
});
}
private void doWrite(AsynchronousSocketChannel channel){
ByteBuffer byteBuffer = ByteBuffer.allocate(1024);
Scanner scanner = new Scanner(System.in);
System.out.println("请输入响应数据:");
String info = scanner.nextLine();
byteBuffer.put(info.getBytes(StandardCharsets.UTF_8));
byteBuffer.flip();
channel.write(byteBuffer, byteBuffer, new CompletionHandler<Integer, ByteBuffer>() {
@Override
public void completed(Integer result, ByteBuffer attachment) {
doRead(channel);
}
@Override
public void failed(Throwable exc, ByteBuffer attachment) {
exc.printStackTrace();
}
});
}
}
- 客户端
package com.xatu.netWorkPractice.aio;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.AsynchronousSocketChannel;
import java.nio.charset.StandardCharsets;
import java.util.Scanner;
import java.util.concurrent.ExecutionException;
public class MyAIOClient {
private AsynchronousSocketChannel channel;
public MyAIOClient(String host, int port){
init(host, port);
}
public void init(String host, int port){
try {
channel = AsynchronousSocketChannel.open();
channel.connect(new InetSocketAddress(host, port));
System.out.println("客户端已启动...");
} catch (IOException e) {
e.printStackTrace();
}
}
public void write(String line){
ByteBuffer buffer = ByteBuffer.allocate(1024);
buffer.put(line.getBytes(StandardCharsets.UTF_8));
buffer.flip();
channel.write(buffer);
}
public void read(){
ByteBuffer buffer = ByteBuffer.allocate(1024);
try {
channel.read(buffer).get();
buffer.flip();
System.out.println("来自服务器端数据:"+new String(buffer.array()));
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
}
}
public void shutDown(){
try {
if (channel != null){
channel.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
MyAIOClient client = new MyAIOClient("127.0.0.1", 9999);
try {
while (true) {
System.out.println("请输入请求数据:");
Scanner scanner = new Scanner(System.in);
String info = scanner.nextLine();
client.write(info);
client.read();
if ("".equals(info) || "exit".equals(info)) {
break;
}
}
}finally {
client.shutDown();
}
}
}