PipedWriter是字符管道輸出流,繼承自Writer,功能與PipedOutputStream相似,經過與PipedReader組合使用實現相似管道的功能,在多線程環境下,一個線程使用PipedWriter寫入數據,經過管道將數據傳遞到管道另外一端的字符輸入流內部緩衝區(實際是經過當前字符管道輸出流綁定的字符管道輸入流對象sink的receive方法將數據存儲到字符輸入流的內部字符緩衝區實現的),其餘線程去讀該內部緩衝區的字符數據,實現線程間通訊。java
package java.io; public class PipedWriter extends Writer { /** 管道綁定的字符輸入流對象 **/ private PipedReader sink; /* * 當前管道字符輸出流的狀態,獨立於管道另外一端字符輸入流的狀態 */ private boolean closed = false; }
/** * 構造函數,調用connect爲當前對象與指定字符管道輸入流對象創建鏈接 */ public PipedWriter(PipedReader snk) throws IOException { connect(snk); } /** * 構造函數,空實現,還沒與管道的字符輸入流創建鏈接,在使用以前必須先創建鏈接不管是管道數據接收端PipedReader仍是 * 仍是數據寫入端PipedWriter調用connect創建鏈接 */ public PipedWriter() { }
PipedWriter的構造函數邏輯很是簡單,兩種構造函數一種什麼都沒作只是建立一個未創建管道鏈接的對象,另外一個構造函數在實例化的同時調用connect建立了與指定字符管道輸入流對象的管道鏈接,以後PipedWriter主要是基於這個指定的管道輸入流對象操做管道數據。數組
public void write(int c) throws IOException { if (sink == null) { throw new IOException("Pipe not connected"); } sink.receive(c); }
方法邏輯很簡單就是在開頭作了管道綁定的接收端字符管道輸入流對象sink的判空,若不爲空則調用它的receive方法接收寫入的單個字符c,receive的內部方法邏輯可參照上篇PipedReader對於receive方法的解析多線程
/** * 爲當前管道輸出流對象鏈接指定的管道輸入流對象snk,若當前管道輸出流以前已經創建與其餘字符管道輸入流的鏈接則拋出 * IOException異常 */ public synchronized void connect(PipedReader snk) throws IOException { if (snk == null) { throw new NullPointerException(); } else if (sink != null || snk.connected) { throw new IOException("Already connected"); } else if (snk.closedByReader || closed) { throw new IOException("Pipe closed"); } sink = snk; snk.in = -1; snk.out = 0; snk.connected = true; } /** * 將指定字符數組cbuf從off位置開始len個字符寫入管道綁定的字符管道輸入流對象內部緩衝區中 * 若是一個線程正在讀取鏈接的字符管道輸入流內部緩衝區字節數據,這時候當前線程掛掉那麼會拋出一個IO異常 */ public void write(char cbuf[], int off, int len) throws IOException { //管道綁定的字符管道輸入流對象爲空 if (sink == null) { throw new IOException("Pipe not connected"); } /** 校驗字符數組起始位置參數off **/ else if ((off | len | (off + len) | (cbuf.length - (off + len))) < 0) { throw new IndexOutOfBoundsException(); } //將字符數組數據寫入管道綁定的字符輸入流內部緩衝區 sink.receive(cbuf, off, len); } /** * 刷新管道輸出流,主要是經過喚醒管道輸入流等待讀取線程讀取數據實現刷新的。 */ public synchronized void flush() throws IOException { if (sink != null) { if (sink.closedByReader || closed) { throw new IOException("Pipe closed"); } synchronized (sink) { sink.notifyAll(); } } } /** * 關閉當前管道輸出流對象,釋放與此有關的系統資源,實際是調用綁定的管道輸入流對象sink的reveivedLast方法 * 更新sink管道寫入端狀態成員變量closedByWriter並喚醒其餘等待線程 */ public void close() throws IOException { closed = true; if (sink != null) { sink.receivedLast(); } }