java aio通过asynchronouschannel系列类和completionhandler实现异步非阻塞io,由os通知完成并触发回调;completionhandler中v为结果类型、a为上下文附件,含completed与failed两个方法;需注意线程池调用、handler一次性、-1 eof处理及bytebuffer正确翻转与清理。

Java 中的 AIO(Asynchronous I/O,异步非阻塞 IO)通过 java.nio.channels.AsynchronousChannel 系列类实现,核心是使用 CompletionHandler 处理异步操作完成后的回调逻辑。它不依赖轮询或显式线程阻塞,而是由操作系统底层通知 JVM 操作完成,再触发你定义的回调。
CompletionHandler 接口结构与作用
CompletionHandler<v></v> 是一个泛型接口,两个类型参数含义如下:
-
V:异步操作的返回结果类型,如
Integer(读/写字节数)、Void(连接操作) -
A:附加对象(attachment),用于在发起异步调用时传入上下文信息,比如
ByteBuffer、自定义会话对象等
它定义两个方法:
-
completed(V result, A attachment):操作成功完成时被调用 -
failed(Throwable exc, A attachment):操作失败时被调用
以 AsynchronousSocketChannel 为例:异步连接 + 读写
下面是一个简化的客户端示例,演示如何用 CompletionHandler 实现连接、发送、接收全流程:
Java项目代码review工具。分析Git变更+完整调用链路上下文,推断业务需求,进行多维度评分和分类汇总,生成完整PRD文档。包含细粒度Java代码审查清单(Null安全、异常处理、Streams、并发、equals/hashCode、资源管理、API设计、性能、MyBatis/ORM、事务边界、SQL/DD...
1. 建立异步连接
AsynchronousSocketChannel channel = AsynchronousSocketChannel.open();
channel.connect(new InetSocketAddress("localhost", 8080), null,
new CompletionHandler<void void>() {
@Override
public void completed(Void result, Void attachment) {
System.out.println("连接成功");
// 启动异步读取
ByteBuffer buffer = ByteBuffer.allocate(1024);
channel.read(buffer, buffer, new ReadHandler(channel));
}
@Override
public void failed(Throwable exc, Void attachment) {
System.err.println("连接失败: " + exc.getMessage());
}
});
</void>
2. 自定义 ReadHandler 处理读取完成
static class ReadHandler implements CompletionHandler<integer bytebuffer> {
private final AsynchronousSocketChannel channel;
ReadHandler(AsynchronousSocketChannel channel) {
this.channel = channel;
}
@Override
public void completed(Integer bytesRead, ByteBuffer buffer) {
if (bytesRead == -1) {
System.out.println("对端关闭连接");
closeChannel();
return;
}
buffer.flip();
byte[] data = new byte[buffer.remaining()];
buffer.get(data);
System.out.println("收到:" + new String(data).trim());
buffer.clear();
// 继续读
channel.read(buffer, buffer, this);
}
@Override
public void failed(Throwable exc, ByteBuffer buffer) {
System.err.println("读取失败:" + exc.getMessage());
closeChannel();
}
private void closeChannel() {
try { channel.close(); } catch (IOException ignored) {}
}
}
</integer>
关键注意事项
-
CompletionHandler的方法由 系统线程池(ForkJoinPool.commonPool 或 AsynchronousChannelGroup 配置的线程池) 调用,不是你发起调用的线程 —— 所以不要假设线程上下文(如 ThreadLocal)一致 - 每次异步操作(如
read/write)都需重新提交 handler;它是一次性的,不会自动重复注册 - 务必检查
read返回值:-1表示 EOF(对端关闭),需主动关闭通道 - 缓冲区(
ByteBuffer)在回调中可能仍被内核使用,务必在completed中flip()后读取,并在继续下一次read前clear()或compact() - 推荐使用 lambda 简化 handler,但注意捕获变量不可变;复杂逻辑建议用静态内部类或独立类
替代方案:Future 方式(不推荐用于高并发场景)
除了 CompletionHandler,AIO 也支持返回 Future:
Future<integer> future = channel.read(buffer); Integer bytesRead = future.get(); // 阻塞等待 —— 这就失去了“异步非阻塞”的意义 </integer>
这种方式违背 AIO 设计初衷,仅适合简单测试或低频调用,生产环境应始终优先使用 CompletionHandler。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










