java nio的pipe是同一进程内线程间单向通信的轻量级通道,由sinkchannel(写入端)和sourcechannel(读取端)组成,阻塞模式下天然线程安全,适用于生产者-消费者模型,需显式关闭通道以释放资源。

Java NIO 的 Pipe 是专为**同一进程内线程间单向通信**设计的轻量级通道,不涉及操作系统管道,完全在 JVM 内存中完成数据传递。它由一对关联的 Pipe.SinkChannel(写入端)和 Pipe.SourceChannel(读取端)组成,天然线程安全,适合生产者-消费者模型。
创建 Pipe 并获取两端通道
调用 Pipe.open() 创建管道实例,随后分别获取写入端和读取端:
Pipe pipe = Pipe.open();-
Pipe.SinkChannel sink = pipe.sink();—— 生产者线程写入数据 -
Pipe.SourceChannel source = pipe.source();—— 消费者线程读取数据
注意:两个通道默认处于阻塞模式,无需额外配置;若需非阻塞,可调用 sink.configureBlocking(false),但需配合 Selector 使用,对简单线程通信反而增加复杂度,一般保持阻塞即可。
生产者线程:通过 SinkChannel 写入数据
使用 ByteBuffer 向 sink 写入字节数据,必须确保 buffer 处于“写模式”(即 clear() 或 flip() 后已重置):
- 准备数据:
buffer.put("hello".getBytes()); buffer.flip(); - 写入:
sink.write(buffer); - 每次写入后建议检查返回值(实际写入字节数),若为 0 表示缓冲区满(Pipe 内部有固定容量,默认约 1MB),需等待消费者读取腾出空间
写入完成后无需关闭 sink,否则管道中断;正常流程中只需保证数据写完即可。
消费者线程:通过 SourceChannel 读取数据
从 source 读取数据时,ByteBuffer 需处于“读模式”(即 flip() 后 position ≤ limit):
- 分配缓冲区:
ByteBuffer buffer = ByteBuffer.allocate(1024); - 读取:
int bytesRead = source.read(buffer); - 若
bytesRead > 0,调用buffer.flip()然后提取数据;若为-1表示写入端已关闭;若为0表示当前无数据可读(阻塞模式下不会返回 0)
读取端通常在一个循环中持续调用 read(),直到明确结束信号(如收到特定终止消息或写入端关闭)。
关闭与资源释放
Pipe 不占用文件描述符,但通道仍需显式关闭以释放内部资源:
- 写入端关闭:
sink.close();→ 会触发读取端后续read()返回-1 - 读取端关闭:
source.close();→ 不影响写入,但再读将抛ClosedChannelException - 推荐由生产者线程在写完所有数据后关闭
sink,消费者检测到-1即退出循环并关闭source
不关闭也不会导致严重泄漏,但属于良好实践。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











