管道流
管道流用于在线程之间传递数据。一个线程写入管道输出流,另一个线程从管道输入流读取。
# 1. 核心类
字节管道流:
PipedInputStreamPipedOutputStream
字符管道流:
PipedReaderPipedWriter
它们必须成对连接。
# 2. 字节管道示例
import java.io.PipedInputStream;
import java.io.PipedOutputStream;
import java.nio.charset.StandardCharsets;
public class PipedStreamDemo {
public static void main(String[] args) throws Exception {
PipedInputStream input = new PipedInputStream();
PipedOutputStream output = new PipedOutputStream(input);
Thread producer = new Thread(() -> {
try (output) {
output.write("hello pipe".getBytes(StandardCharsets.UTF_8));
} catch (Exception e) {
throw new RuntimeException(e);
}
});
Thread consumer = new Thread(() -> {
try (input) {
byte[] buffer = new byte[1024];
int len = input.read(buffer);
System.out.println(new String(buffer, 0, len, StandardCharsets.UTF_8));
} catch (Exception e) {
throw new RuntimeException(e);
}
});
consumer.start();
producer.start();
}
}
# 3. 管道流的特点
管道流有几个关键特点:
- 适合线程间一边生产、一边消费。
- 内部缓冲区有限,写入过快而读取过慢会阻塞。
- 如果读写双方没有正确启动,容易死锁。
- 不适合复杂的多生产者、多消费者场景。
# 4. 和 BlockingQueue 的对比
实际业务中,线程间传递数据更常用 BlockingQueue。
| 对比项 | 管道流 | BlockingQueue |
|---|---|---|
| 数据形式 | 字节或字符流 | 任意对象 |
| 使用难度 | 较高 | 较低 |
| 背压能力 | 有限缓冲阻塞 | 队列容量控制 |
| 业务表达 | 偏底层 | 更直观 |
| 常见程度 | 较少 | 很常见 |
如果数据本身就是流式字节,管道流有价值。如果是业务对象,优先考虑队列。
# 5. 使用注意点
- 不要在同一个线程中同时读写管道,容易阻塞。
- 必须连接输入端和输出端。
- 要正确关闭输出端,否则读取端可能一直等待。
- 异常处理要能通知对端,否则另一端可能一直阻塞。
# 专家实践清单
| 检查项 | 要求 | 风险 |
|---|---|---|
| 线程模型 | 读写端放在不同线程 | 同线程读写容易死等 |
| 连接关系 | 输入端和输出端必须连接 | 未连接会抛异常 |
| 关闭协议 | 输出端完成后关闭 | 读取端可能一直等待 |
| 异常传递 | 一端失败要通知另一端 | 对端阻塞无法退出 |
管道流的协作模型:
生产线程
│ PipedOutputStream
▼
管道缓冲区
│ PipedInputStream
▼
消费线程
# Tips 快问快答
Q:管道流解决什么问题? A:在两个线程之间以流的方式传递数据。
Q:管道流能跨进程通信吗? A:不能,它是 JVM 内线程间通信工具。
Q:为什么不能在同一线程中同时读写? A:管道缓冲区满或空时会阻塞,单线程容易互相等待。
Q:管道流和 BlockingQueue 怎么选?
A:传字节流可用管道流,传对象任务通常 BlockingQueue 更清晰。
Q:读取端什么时候知道结束?
A:输出端关闭后,读取端最终读到 -1。
Q:管道缓冲区满了会怎样? A:写入端会阻塞,直到读取端消费数据。
Q:生产代码常用管道流吗? A:不多,更多使用队列、响应式流或消息中间件。
Q:管道流最重要的边界是什么? A:要设计关闭、异常通知和线程退出协议。
# 6. 总结
管道流是 Java IO 中用于线程间流式通信的工具,适合学习流式生产消费模型。生产业务中它出现频率不高,因为 BlockingQueue、响应式流、消息队列等方案通常更易维护。
上次更新: 2026/06/25, 14:19:18