java中pipedinputstream与pipedoutputstream通过内存管道实现线程间通信,需先connect()连接、分线程读写,注意缓冲区大小、flush()调用及异常处理。

Java 中用 PipedInputStream 和 PipedOutputStream 实现线程间通信,核心是让两个线程通过管道“一写一读”,数据在内存中直接传递,无需文件或网络开销。关键在于:必须先建立连接(connect()),且读写操作需并发执行,否则会阻塞。
创建并连接管道流
管道流必须成对使用,并显式连接。常见写法是用 PipedOutputStream 构造时传入 PipedInputStream,或调用 connect() 方法。推荐在构造后立即连接,避免线程启动后才连接导致死锁。
- 方式一(推荐):
PipedInputStream pis = new PipedInputStream();<br>PipedOutputStream pos = new PipedOutputStream(pis);
- 方式二:
PipedInputStream pis = new PipedInputStream();<br>PipedOutputStream pos = new PipedOutputStream();<br>pis.connect(pos); // 或 pos.connect(pis)
注意:连接方向要一致——PipedOutputStream 是数据源头,PipedInputStream 是接收端;调用 connect() 时,参数必须是对方实例。
在不同线程中分别读写
一个线程向 PipedOutputStream 写数据,另一个线程从 PipedInputStream 读数据。写线程不能等读线程就绪再开始写,否则可能因缓冲区满而阻塞;读线程应尽早启动,持续消费数据。
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
- 写线程示例:
pos.write("hello".getBytes()); pos.flush(); - 读线程示例:
int b; while ((b = pis.read()) != -1) { System.out.print((char)b); } - 务必在写完后调用
flush(),尤其小数据量时,避免因缓冲未触发而卡住
处理异常与资源释放
管道流一旦断开(如写线程异常退出、流被关闭),读线程会抛出 IOException(如 “Write end dead”)。因此读写逻辑都应包裹 try-catch,并在 finally 中关闭流。
-
pis.close()会中断读取并使关联的pos抛异常 -
pos.close()会通知读端流已结束(read()返回 -1) - 建议:写线程结束后主动
pos.close(),读线程检测到 -1 后退出并关闭pis
实际使用注意事项
管道流默认缓冲区仅 1024 字节,写入超过时会阻塞,直到读线程消费。不适合传输大量数据或对实时性要求极高的场景。更现代的替代方案包括 BlockingQueue、Exchanger 或 ConcurrentLinkedQueue + 显式同步。
- 不要在同一线程中既读又写,会导致死锁
- 避免在构造管道流后长时间不启动读/写线程
- 调试时可加日志确认连接时机和数据流向,防止“没连上却以为通了”
不复杂但容易忽略连接和线程启动顺序,理清“谁连谁”“谁先跑”,就能稳定通信。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










