java nio pipe是同一jvm内两线程间单向低开销通信机制,基于内核环形缓冲区,含sinkchannel(只写)和sourcechannel(只读),需手动管理bytebuffer模式与状态,通过close()触发read()返回-1实现优雅终止。

Java NIO 的 Pipe 是专为同一 JVM 内两个线程间单向、低开销数据传输设计的原生机制。它不依赖锁、不序列化、零拷贝,底层复用操作系统内核的环形缓冲区(默认约 8 KiB),天然适配生产者-消费者模型。
创建管道并获取两端通道
调用 Pipe.open() 一次性获得强绑定的一对通道:
-
Pipe.SinkChannel:只写端,是唯一数据入口,不可读 -
Pipe.SourceChannel:只读端,是唯一数据出口,不可写
两者共享同一内核资源,任意一端关闭,另一端后续 I/O 操作会立即抛出 ClosedChannelException。
写线程:非阻塞写入 + 手动缓冲区管理
必须设为非阻塞,否则可能永久挂起:
sinkChannel.configureBlocking(false)- 写入前确保
ByteBuffer处于写模式,并调用flip()(使 position=0,limit=实际数据长度) -
write(buffer)返回值关键:
– 返回 0 → 缓冲区满,需稍后重试(建议Thread.yield()或交由调度器)
– 小于 buffer 剩余容量 → 调用buffer.compact()整理未写部分再继续
– 写完可调用buffer.clear()复用
⚠️ 常见错误:忘记 flip() 导致写入 0 字节;关闭 sink 后仍尝试写入。
读线程:安全读取 + 显式状态切换
SourceChannel 支持注册到 Selector(SinkChannel 不支持):
sourceChannel.configureBlocking(false)sourceChannel.register(selector, SelectionKey.OP_READ)-
read(buffer)返回值含义:
– 返回 -1 → 写入端已关闭,应终止读取循环
– 返回 0 → 当前无数据(非错误,非阻塞下的正常现象)
– 返回正数 → 实际读取字节数,随后必须buffer.flip()切换至读模式提取数据,处理完再buffer.clear()
⚠️ 常见错误:未区分 -1 和 0 导致死循环;读取后未 flip() 导致取出乱码或空内容。
消息边界与优雅终止需协作约定
Pipe 本身不提供分包、消息头或关闭通知机制:
- 不推荐用“写入空 buffer”作为结束信号(
read()返回 0 表示暂无数据,不是流结束) - 可行方式包括:
– 写入特定终止标记(如 UTF-8 编码的"END")
– 在每条消息前写入 4 字节 int 表示长度(需双方约定协议) - 写线程调用
sinkChannel.close()后,读线程下次read()将返回 -1,这是标准终止信号
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











