AsynchronousFileChannel提供基于操作系统AIO的真正异步文件I/O,通过open()工厂方法创建,支持带位置的异步读写与CompletionHandler回调,需用direct buffer并显式关闭。

Java NIO 的 AsynchronousFileChannel 提供真正的异步文件 I/O(基于操作系统底层 AIO,如 Linux 的 io_uring 或 Windows 的 IOCP),不阻塞线程,适合高并发、大文件或后台批量处理场景。它不依赖线程池轮询,而是通过回调或 Future 通知完成结果。
创建 AsynchronousFileChannel 实例
不能直接 new,必须通过静态工厂方法打开:
- 用
AsynchronousFileChannel.open(Path, Set<OpenOption>, ExecutorService)—— 指定自定义线程池(可选,传 null 则用默认 ForkJoinPool) - 常用选项:
StandardOpenOption.READ、StandardOpenOption.WRITE、StandardOpenOption.CREATE、StandardOpenOption.TRUNCATE_EXISTING - 示例:
AsynchronousFileChannel channel = AsynchronousFileChannel.open(
Paths.get("data.txt"),
Set.of(READ, WRITE, CREATE),
ForkJoinPool.commonPool());
异步读取:使用 CompletionHandler
推荐方式,避免阻塞,逻辑清晰:
- 调用
read(ByteBuffer, position, attachment, handler) -
position是文件偏移量(从哪开始读),attachment是任意上下文对象(如请求 ID、缓冲区引用) -
CompletionHandler<Integer, ? super A>中:
✓completed(Integer result, A attachment):result 是实际读到的字节数(-1 表示 EOF)
✗failed(Throwable exc, A attachment):出错时触发(如权限不足、文件被删) - 注意:ByteBuffer 必须是 direct buffer(
ByteBuffer.allocateDirect())才能获得最佳性能;若用 heap buffer,AIO 会自动复制,但有额外开销
异步写入:同样用 CompletionHandler
写操作也支持指定位置,适合随机写或追加:
立即学习“Java免费学习笔记(深入)”;
- 调用
write(ByteBuffer, position, attachment, handler) - 如果
position == -1,表示追加到文件末尾(等效于先size()再写) - 写入成功后不会自动更新文件长度——如果写越界(如 position + buffer.remaining() > 当前 size),文件会自动扩展(类似普通 write)
- 务必在
completed中检查返回值是否等于 buffer.remaining(),否则可能只写了一部分(尤其在磁盘满或中断时)
关闭与资源管理
AsynchronousFileChannel 实现了 AutoCloseable,务必显式关闭:
- 用 try-with-resources 最安全:
try (AsynchronousFileChannel ch = AsynchronousFileChannel.open(...)) { ... } - 关闭后,已提交但未完成的操作仍会执行并回调,但新调用会立即抛
ClosedChannelException - 不要在
completed()或failed()回调里直接关闭 channel(可能引发竞态),应在外部统一管理生命周期


















