2009-12-08 151 views
18

我有兩個線程。其中一個寫入PipedOutputStream,另一個從相應的PipedInputStream讀取。背景是,一個線程正在從遠程服務器下載一些數據,並通過管道流將其多路複用到其他幾個線程。PipedInputStream - 如何避免「java.io.IOException:管道損壞」

的問題是,有時(特別是下載大(> 50MB的時候)文件)我得到產生java.io.IOException:管道試圖從的PipedInputStream讀取時壞
Javadoc說A pipe is said to be broken if a thread that was providing data bytes to the connected piped output stream is no longer alive.
確實,我的寫作線程在將所有數據寫入PipedOutputStream後真的死亡。

任何解決方案?我怎樣才能防止PipedInputStream拋出這個異常?即使寫作線程完成了他的工作,我也希望能夠讀取寫入PipedOutputStream的所有數據。 (如果有人知道如何繼續寫入線程直到讀取所有數據,這個解決方案也可以接受)。

回答

17

使用java.util.concurrent.CountDownLatch,並且不會在第二個線程發出信號並且已經完成從管道讀取之前結束第一個線程。

更新:快速和骯髒的代碼來說明我的評論下面

final PipedInputStream pin = getInputStream(); 
    final PipedOutputStream pout = getOutputStream(); 

    final CountDownLatch latch = new CountDownLatch(1); 

    InputStream in = new InputStream() { 

     @Override 
     public int read() throws IOException { 
      return pin.read(); 
     } 

     @Override 
     public void close() throws IOException { 
      super.close(); 
      latch.countDown(); 
     } 
    }; 


    OutputStream out = new OutputStream(){ 

     @Override 
     public void write(int b) throws IOException { 
      pout.write(b); 
     } 

     @Override 
     public void close() throws IOException { 
      while(latch.getCount()!=0) { 
       try { 
        latch.await(); 
       } catch (InterruptedException e) { 
        //too bad 
       } 
      } 
      super.close(); 
     } 
    }; 

    //give the streams to your threads, they don't know a latch ever existed 
    threadOne.feed(in); 
    threadTwo.feed(out); 
+0

不錯的功能,它肯定是+1,但它需要在不同線程之間共享一個CountDownLatch實例。這不太好,因爲寫作和閱讀主題是在不同的地方創建的,我希望他們不要彼此瞭解。我現在的架構是這樣的,他們只知道應該寫入/讀取給定流中的數據。 – levanovd 2009-12-08 11:48:05

+0

然後,可能會擴展Piped [In | Out] putStream來處理CountDownLatch的操作。 – Jerome 2009-12-08 11:53:04

+0

或編寫自己的包裝管道和鎖存器的Input/OutputStream(請參閱我在答案中添加的示例代碼) – Jerome 2009-12-08 14:33:22

0

PipedInputStreamPipedOutputStream被破壞(關於線程)。他們假設每個實例都綁定到一個特定的線程。這是奇怪的。我建議使用你自己的(或者至少不同的)實現。

+0

此響應不提供任何價值。這些課程以什麼方式假設這一點? – matsa 2017-11-29 13:40:51

4

當你正在使用它的線程結束時,你正在關閉你的PipedOutputStream嗎?您需要這樣做,以便將其中的字節刷新到相應的PipedInputStream

+0

是的,我關閉它。 – levanovd 2009-12-08 14:19:17

+0

我真的覺得別的東西在這裏出了問題,在任何情況下,如果寫入線程正常結束,你永遠不會收到損壞的管道。如果它的數據不適合'PipedInputStream',它應該阻塞直到有空間。 – wds 2009-12-08 16:32:43

+2

不清楚'close()'意味着'flush()'。 – Raedwald 2012-02-28 13:59:58

相關問題