2017-10-09 247 views
1

我有一個不斷生成數據並將其寫入到其自己線程上的ByteArrayOutputStream的類。我有第二個線程獲取對此ByteArrayOutputStream的引用。我希望第二個線程讀取任何數據(並清空)ByteArrayOutputStream,然後在沒有得到任何字節和睡眠時停止。睡眠後,我想讓它嘗試獲取更多數據並再次清空。從ByteArrayOutputStream中讀取數據並將其寫入

我在網上看到的例子說使用PipedOutputStream。如果我的第一個線程使ByteArrayOutputStream從一個單獨的可重用庫中可用於外界,我看不到如何將inputStream連接到它。

如何設置PipedInputStream將其連接到ByteArrayOutputStream以從上面讀取它?另外,當從ByteArrayOutputStream讀取最後一個塊時,是否會看到bytesRead == -1,指示outputStream何時從第一個線程關閉?

非常感謝, 麥克

回答

3

刻錄到PipedOutputStream直接(即,不使用ByteArrayOutputStream的話)。它們都擴展爲OutputStream,因此具有相同的接口。

PipedOutputStreamPipedInputStream中有connect方法用於將兩個管道連接在一起,或者您可以使用其中一個構造函數創建一對。

寫入PipedOutputStreamPipedInputStream緩衝區已​​滿將阻止,並從PipedInputStream讀取時,緩衝區爲空會阻塞,因此,生產者線程將休眠(塊),如果它變得「超前」消費的反之亦然。

在重新檢查緩衝區之前,阻塞線程等待1000ms之後,所以最好在寫入完成後刷新輸出(如果它正在睡眠,這將喚醒讀取器)。

當您關閉生產者線程中的輸出流時,您的輸入流將會看到EOF(bytesRead == -1)。

import java.io.*; 
import java.util.concurrent.ExecutorService; 
import java.util.concurrent.Executors; 

public class PipeTest { 
    public static void main(String[] args) throws IOException { 
     PipedOutputStream out = new PipedOutputStream(); 
     // Wire an input stream to the output stream, and use a buffer of 2048 bytes 
     PipedInputStream in = new PipedInputStream(out, 2048); 

     ExecutorService executor = Executors.newCachedThreadPool(); 

     // Producer thread. 
     executor.execute(() -> { 
      try { 
       for (int i = 0; i < 10240; i++) { 
        out.write(0); 
        // flush to wake the reader 
        out.flush(); 
       } 
       out.close(); 
      } catch (IOException e) { 
       throw new UncheckedIOException(e); 
      } 
     }); 

     // Consumer thread. 
     executor.execute(() -> { 
      try { 
       int b, read = 0; 
       while ((b = in.read()) != -1) { 
        read++; 
       } 
       System.out.println("Read " + read + " bytes."); 
      } catch (IOException e) { 
       throw new UncheckedIOException(e); 
      } 
     }); 

     executor.shutdown(); 
    } 
} 
+0

這太棒了。感謝您爲我清理! – Mike

+0

嗨teppic,我已經編碼了所有這一切,似乎我的生產者線程必須填充連接的PipedInputStream的緩衝區之前,它的讀取踢。這是有道理的,但這是否意味着,如果我的製作人從麥克風輸出數據,會有一些時期會失去投入?我應該考慮某種「雙緩衝」來處理這個問題嗎? – Mike

+1

嘗試在每次寫入後清空輸出流。 – teppic

相關問題