PipedInputStream和PipedOutputStream是Java中用于线程间字节传输的阻塞式管道流,需成对绑定、分线程读写,通过1024字节缓冲区自动传递数据,写满或无数据时分别阻塞,异常关闭可触发EOF或异常通知。

PipedStream(准确说是 PipedInputStream 和 PipedOutputStream)是 Java 标准库中专为**线程间字节数据传输**设计的一对管道流。它们必须成对使用,且需在不同线程中操作:一个线程写入 PipedOutputStream,另一个线程从关联的 PipedInputStream 读取,数据通过内存缓冲区自动传递。
核心机制:绑定与阻塞
两个流必须通过 connect() 方法或构造函数绑定(推荐用构造函数直接关联),形成“管道”。一旦绑定:
- 写线程调用
write()时,若读线程未及时读取,写操作会**阻塞**,直到缓冲区有空闲空间; - 读线程调用
read()时,若管道中无数据,读操作会**阻塞**,直到有数据写入或流关闭; - 缓冲区默认大小为 1024 字节,可构造时指定;
- 任一线程异常关闭输出流(或抛出 IOException),输入流会感知到 EOF 或异常,避免死锁。
典型使用步骤
按顺序执行以下操作,确保线程安全和正确性:
分析 Java Spring Boot 后端 Controller 代码,自动生成 Markdown 格式的接口文档。当用户说“生成 Java 接口文档”、“生成 API 文档”、“从 Spring 代码生成文档”时触发。
- 创建一对绑定的流:
PipedInputStream pis = new PipedInputStream();,PipedOutputStream pos = new PipedOutputStream(pis);(或反过来,用pis.connect(pos)); - 启动读线程:在新线程中打开
pis,循环调用read()或read(byte[]),处理接收到的字节; - 启动写线程:在另一线程中向
pos写入字节(如pos.write(data)),写完可调用pos.close()通知读端结束; - 注意异常捕获:I/O 异常(如
IOException)可能由对方线程关闭流触发,需在读/写循环中妥善处理。
简单示例:字符串传输
以下代码演示主线程写入字符串,子线程读取并打印:
立即学习“Java免费学习笔记(深入)”;
// 创建管道
PipedInputStream pis = new PipedInputStream();
PipedOutputStream pos = new PipedOutputStream(pis);
// 启动读线程
new Thread(() -> {
try (PipedInputStream in = pis) {
int b;
while ((b = in.read()) != -1) {
System.out.print((char) b);
}
System.out.println(" —— 读取完成");
} catch (IOException e) {
System.err.println("读取异常: " + e.getMessage());
}
}).start();
// 主线程写入
try (PipedOutputStream out = pos) {
out.write("Hello, PipedStream!".getBytes(StandardCharsets.UTF_8));
} catch (IOException e) {
System.err.println("写入异常: " + e.getMessage());
}
运行后输出:Hello, PipedStream! —— 读取完成。注意:必须先启动读线程再写入,否则写线程可能因缓冲区满而永久阻塞(除非设置超时或合理控制写入量)。
注意事项与常见陷阱
- 不能在同一线程中读写:会导致死锁(自己写自己读,双方都等待对方动作);
-
流未绑定就使用会抛
IOException:“Pipe not connected”; - 读线程应尽早启动,避免写线程因缓冲区满被挂起;
- 如需传输结构化数据(如对象),建议包装为
ObjectInputStream/ObjectOutputStream,但需确保两端严格同步且类可序列化; - 不适用于高吞吐或低延迟场景,缓冲区小、阻塞模型限制性能;替代方案可考虑
BlockingQueue<byte></byte>或Exchanger等更灵活的并发工具。

















