PipedInputStream / PipedOutputStream 實現線程間內存級數據傳遞,無需中間字節數組,直接「管道」連接輸出流到輸入流。配合多線程實現生產者-消費者模式,讀取阻塞直到有數據寫入。
read() 阻塞,寫端 write() 可阻塞(緩衝區滿)connect() 或構造器綁定import java.io.*;
/** 讀取線程(消費者) */
class ReadPipe implements Runnable {
private PipedInputStream in;
public ReadPipe(PipedInputStream in) { this.in = in; }
@Override public void run() {
System.out.println("【讀線程】啟動,等待數據...");
byte[] buf = new byte[1024];
try {
int len = in.read(buf); // 阻塞直到有數據
String msg = new String(buf, 0, len);
System.out.println("【讀線程】收到: " + msg);
in.close();
} catch (IOException e) { e.printStackTrace(); }
}
}
/** 寫入線程(生產者) */
class WritePipe implements Runnable {
private PipedOutputStream out;
public WritePipe(PipedOutputStream out) { this.out = out; }
@Override public void run() {
System.out.println("【寫線程】啟動,5 秒後發送數據...");
try {
Thread.sleep(5000); // 模擬延遲
out.write("我是通過管道流傳遞的數據".getBytes("UTF-8"));
System.out.println("【寫線程】發送完成");
out.close();
} catch (Exception e) { e.printStackTrace(); }
}
}
/** 主程序:創建管道、啟動線程 */
public class PipeDemo {
public static void main(String[] args) throws IOException {
// 1. 創建管道兩端
PipedInputStream in = new PipedInputStream();
PipedOutputStream out = new PipedOutputStream();
// 2. 連接:輸出流 → 輸入流
in.connect(out); // 或 new PipedInputStream(out)
// 3. 啟動線程
new Thread(new ReadPipe(in), "Reader").start();
new Thread(new WritePipe(out), "Writer").start();
System.out.println("主線程結束,子線程繼續運行...");
}
}
主線程結束,子線程繼續運行...
【讀線程】啟動,等待數據...
【寫線程】啟動,5 秒後發送數據...
【寫線程】發送完成
【讀線程】收到: 我是通過管道流傳遞的數據

IOException: Pipe not connectednew PipedOutputStream(in, bufferSize) 調整 (JDK 9+)read() 返回 -1(EOF),讀端再關閉IOException/InterruptedException| 方案 | 優勢 | 適用場景 |
|---|---|---|
BlockingQueue | 類型安全、豐富 API (put/take/offer/poll)、可指定容量 | 生產者消費者、任務隊列 |
CompletableFuture | 異步組合、回調地獄解決、異常傳播 | 異步計算編排 |
Reactive Streams (Project Reactor/RxJava) | 背壓、流操作符、函數式 | 高吞吐異步流處理 |
| 管道流 | 流式 API、兼容舊代碼、無第三方依賴 | 輕量級字節流傳遞、重定向 System.in/out |
管道流是 JDK 1.1 時代的線程間通信機制,雖然被更高級的併發工具取代,但在流式字節數據傳遞、重定向標準輸入輸出、測試模擬流等場景仍有獨特價值。理解其阻塞語義與連接生命週期,有助於排查舊系統相關問題。