2009-12-08 31 views
18

Tôi có hai luồng. Một trong số chúng ghi vào PipedOutputStream, một cái khác đọc từ PipedInputStream tương ứng. Bối cảnh là một luồng đang tải xuống một số dữ liệu từ máy chủ từ xa và ghép nối nó với một số luồng khác thông qua các luồng đường ống.PipedInputStream - Cách tránh "java.io.IOException: Pipe broken"

Vấn đề là đôi khi (nhất là khi tải lớn (> 50Mb) files) tôi nhận được java.io.IOException: Ống chia khi cố gắng đọc từ PipedInputStream.
Javadoc nói rằng 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.
Đúng vậy, chuỗi viết của tôi thực sự chết sau khi ghi tất cả dữ liệu của anh ấy vào PipedOutputStream.

Bất kỳ giải pháp? Làm thế nào tôi có thể ngăn PipedInputStream thoát khỏi ngoại lệ này? Tôi muốn để có thể đọc tất cả các dữ liệu đã được viết cho PipedOutputStream ngay cả khi viết thread hoàn thành công việc của mình. (Nếu có ai biết cách tiếp tục viết luồng cho đến khi tất cả dữ liệu được đọc, giải pháp này cũng được chấp nhận).

Trả lời

17

Sử dụng java.util.concurrent.CountDownLatch và không kết thúc chuỗi đầu tiên trước khi chuỗi thứ hai báo hiệu đã đọc xong từ đường ống.

Cập nhật: mã nhanh chóng và dơ bẩn để minh họa cho nhận xét của tôi dưới đây

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

Tính năng tuyệt vời, chắc chắn +1, nhưng nó cần chia sẻ một phiên bản CountDownLatch giữa các chuỗi khác nhau. Điều này không phải là rất tốt, bởi vì viết và đọc chủ đề được tạo ra ở những nơi khác nhau và tôi muốn họ không biết về nhau. Kiến trúc của tôi bây giờ là như vậy mà họ biết chỉ có nên ghi/đọc đến/từ dòng nhất định. – levanovd

+0

Sau đó, có thể bạn có thể mở rộng Piped [In | Out] putStream để xử lý thao tác của CountDownLatch. – Jerome

+0

hoặc viết Input/OutputStream của riêng bạn để bao bọc ống và chốt (xem mã mẫu mà tôi đã thêm vào câu trả lời của tôi) – Jerome

0

PipedInputStreamPipedOutputStream bị hỏng (đối với luồng). Họ cho rằng mỗi cá thể được gắn với một chuỗi cụ thể. Đây là kỳ quái. Tôi đề nghị sử dụng của riêng bạn (hoặc ít nhất là một khác nhau) thực hiện.

+0

Phản hồi này không có giá trị. Theo cách nào các lớp này giả định điều này? – matsa

4

Bạn có đóng PipedOutputStream khi chuỗi đang sử dụng kết thúc không? Bạn cần phải làm điều này để các byte trong nó sẽ bị xóa đi tương ứng với PipedInputStream.

+0

Có, tôi đóng nó. – levanovd

+0

Tôi thực sự nghĩ rằng một cái gì đó khác là đi sai ở đây, trong mọi trường hợp bạn sẽ không bao giờ nhận được một đường ống bị hỏng nếu các chủ đề bằng văn bản kết thúc bình thường. Nếu dữ liệu của nó không vừa với 'PipedInputStream' thì nó sẽ chỉ chặn cho đến khi có chỗ. – wds

+2

Không rõ 'close()' ngụ ý 'flush()'. – Raedwald

Các vấn đề liên quan