AsynchronousFileChannel不维护读写位置,所有操作须显式传入绝对position参数;需手动管理ByteBuffer状态(flip/clear/compact);attachment仅作上下文传递,不自动同步;并发与异常需外部变量显式控制。
asynchronousfilechannel 本身不维护读写位置状态,所有操作都依赖显式传入的 position 参数,这是理解其变量处理的核心。
position 是绝对偏移量,不是游标
每次 read() 或 write() 都必须指定从文件哪个字节位置开始操作。通道内部没有“当前指针”,不会自动递进。比如连续两次调用 read(buffer, 0, ...),都会从开头重复读;若想顺序读取,需手动累加前一次的读取长度作为下一次的 position。
- 适合随机访问场景:可并发发起多个不同 position 的读请求,互不影响
- 不适合流式遍历:不能靠 channel.position() 获取或设置位置,该方法根本不存在
- position 超出文件末尾时,read 返回 0(非 EOF),write 则可能扩展文件(取决于 open 选项)
ByteBuffer 状态需手动管理
异步操作不接管 buffer 生命周期,调用方必须在回调中主动控制其状态,否则数据错乱或丢字节。
- read 回调 onCompleted 中:先
buffer.flip()才能读取有效内容,处理完再buffer.clear()或buffer.compact()准备复用 - write 调用前:确保 buffer 已
flip(),且调用后不能修改 buffer 内容(因底层可能仍在使用) - 推荐对大文件使用 direct buffer:
ByteBuffer.allocateDirect(1024 * 1024),减少 JVM 堆内存压力和拷贝开销
attachment 是上下文载体,不是状态变量
CompletionHandler 的 attachment 参数用于传递自定义对象(如 request ID、file offset 计数器、目标输出流),它不被通道解析或修改,纯属用户逻辑绑定。
- 常见用法:传入一个包含 buffer、nextPosition、totalRead 的自定义类实例,在 completed 中更新 nextPosition 并发起下一轮 read
- 避免在 attachment 中放强引用大对象,防止内存泄漏(尤其 handler 执行延迟时)
- 不要依赖 attachment 在多次回调间保持“线程安全”——它只是参数,无同步保障
资源与异常变量需显式跟踪
AsynchronousFileChannel 不自动管理连接数、并发请求数或失败重试次数,这些都得靠外部变量控制。
- 用 AtomicInteger 记录未完成的 write 请求数,配合计数器限制并发,防 OOM
- 用 volatile boolean 标记整体任务是否取消,onFailed 中检查并停止后续操作
- 捕获 failed() 中的 IOException 子类(如 DiskFullException、AccessDeniedException),按类型做差异化处理

















