AsynchronousFileChannel 的回调机制基于操作系统级异步I/O(如io_uring、I/O Completion Ports),通过CompletionHandler的completed/failed方法由线程池自动触发,不阻塞调用线程、不轮询;position为绝对偏移量,需手动维护;buffer须显式flip/compact,attachment用于传递上下文并关联请求响应。

AsynchronousFileChannel 的回调机制不是“等结果回来再处理”,而是把处理逻辑提前注册好,操作由操作系统底层异步完成,完成后由线程池中某个线程自动触发 completed 或 failed 方法。它不阻塞调用线程,也不依赖轮询,是真正基于系统级异步 I/O(如 Linux io_uring、Windows I/O Completion Ports)的通知模型。
回调接口 CompletionHandler 的核心行为
CompletionHandler
- completed(Integer result, A attachment):操作成功时调用。result 是本次实际读/写的字节数;若为 -1,表示已到文件末尾(仅 read 场景)
- failed(Throwable exc, A attachment):发生 IOException、SecurityException 等异常时调用,exc 包含具体错误原因
attachment 是你传入的任意上下文对象,比如当前 buffer 引用、文件偏移量、任务 ID 或自定义状态容器,用于在回调中关联请求与响应,避免共享变量或外部查找。
回调执行不在原始线程,也不保证顺序
回调由 AsynchronousChannelGroup 关联的线程池(默认是 ForkJoinPool.commonPool())中的某个工作线程执行,和发起 read/write 的线程完全无关。这意味着:
- 不能假设回调发生在主线程或某固定线程上
- 多次异步操作的回调执行顺序不一定与发起顺序一致(尤其当块大小不同、磁盘延迟波动时)
- 若需串行处理(如按顺序拼接数据),得在 attachment 中维护序号或使用显式同步逻辑
buffer 状态必须手动管理
异步操作不会自动翻转或清空 ByteBuffer。在 completed 中处理数据前,必须调用 buffer.flip();处理完准备复用 buffer 发起下一次读写时,应根据场景选择:
AI 舌诊面诊问诊医疗系统 + 诊疗商城系统源码是一套结合 AI 辅助诊断与商品转化的健康类程序,基于浩创云、ThinkPHP(PHP)开发,支持微信服务号与 H5 端,适合做中医舌诊面诊问答、健康建议推送以及配套诊疗商品的运营。
-
buffer.clear():适合每次读写都用全新数据范围(如固定块读取后整体处理) -
buffer.compact():适合流式读取且 buffer 未被完全填满(保留未读部分,为下次读腾出空间)
忽略这一步会导致数据错乱、重复读取或写入越界——这是回调方式下最常被忽略的细节。
发起异步操作时 position 是绝对偏移量
不同于 FileChannel 的内部 position 指针,AsynchronousFileChannel 的每个 read/write 都要显式传入 long position,表示从文件开头算起的字节位置。例如:
- 第 1 块读取:read(buffer, 0L, attachment, handler)
- 第 2 块读取:read(buffer, 1048576L, attachment, handler) // 1MB 后
这种设计让操作天然线程安全、无状态,但也要求你自行维护读写位置逻辑——通常封装在 attachment 对象里,随每次回调传递下去。










