2017-04-26 97 views
0

這是my question here的一種擴展。如何修復ObjectInputStream和ObjectOutputStream的「寫入結束死亡」和「讀取結束死亡」錯誤?

我有3個班。

我的主:

import java.io.*; 

public class ConnectionManager { 
    public static void main(String argv[]) { 

     try { 
      PipedOutputStream pout = new PipedOutputStream(); 
      PipedInputStream pin = new PipedInputStream(pout); 

      Sender s = new Sender(pout,true); 
      Receiver r = new Receiver(pin,true); 
      System.out.println("Starting threads"); 
      s.start(); 
      r.start(); 
     } catch (Exception e) {System.out.println(e);} 
    } 
} 

我的發件人/製作類:

import java.io.*; 

public class Sender extends Thread { 
    ObjectOutputStream oos; 
    boolean primitive; 

    public Sender(OutputStream os, boolean primitive) { 
     try { 
      oos = new ObjectOutputStream(os); 
      this.primitive = primitive; 
     } catch (Exception e) {System.out.println(e);} 
    } 

    public void run() { 
     try { 
      System.out.println("Sending a message"); 
      Thread.sleep(1000); 
      oos.writeInt(99); 
      oos.flush(); 
      System.out.println("Message sent, terminating"); 
      oos.close(); 
     } catch (Exception e) {System.out.println("Sender: " + e);} 
    } 
} 

我的接收器/ Consumer類:

import java.io.*; 

public class Receiver extends Thread { 
    ObjectInputStream ois; 
    boolean primitive; 

    public Receiver(InputStream is, boolean primitive) { 
     try { 
      ois = new ObjectInputStream(is); 
      this.primitive = primitive; 
     } catch (Exception e) {System.out.println(e);} 
    } 

    public void run() { 
     try { 
      System.out.println("waiting for a message"); 
      int x = ois.readInt(); 
      System.out.println("message received: " + x); 
      ois.close(); 
     } catch (Exception e) {System.out.println("Receiver: " + e);} 

    } 
} 

產生這樣的輸出:

Starting threads 
Sending a message 
waiting for a message 
Receiver: java.io.IOException: Write end dead 
Sender: java.io.IOException: Read end dead 

我在this page中讀到我收到這些異常,因爲我沒有關閉管道。但即使我這樣做,我仍然得到它們。我怎樣才能解決這個問題?

編輯:我將類型的流對象從PipedInputStream轉換爲InputStream,然後使用InputStream構造一個新的ObjectInputStream是因爲我希望能夠發送和接收各種類型的數據,而不是隻是int或字節。

回答

0

我保持糾正;並遵循EJP的建議;這裏是一個工作解決方案。

import java.io.*; 
public class ConnectionManager { 
    public static void main(String argv[]) throws Exception { 
     PipedOutputStream pout = new PipedOutputStream(); 
     PipedInputStream pin = new PipedInputStream(pout); 
     Sender s = new Sender(pout); 
     Receiver r = new Receiver(pin); 
     System.out.println("Starting threads"); 
     s.start(); 
     r.start(); 
    } 
} 

class Sender extends Thread { 
    private final OutputStream os; 
    Sender(OutputStream os) { this.os = os; } 
    public void run() { 
    try(ObjectOutputStream oos = new ObjectOutputStream(os)) { 
     oos.writeInt(99); 
     System.out.println("Message sent, terminating"); 
    } catch (Exception e) { 
     System.out.println("Sender: " + e); 
     e.printStackTrace(); 
    } 
    } 
} 

class Receiver extends Thread { 
    private final InputStream is; 
    Receiver(InputStream is) {this.is = is; } 
    public void run() { 
    try(ObjectInputStream ois = new ObjectInputStream(is)) { 
    System.out.println("waiting for a message"); 
    int x = ois.readInt(); 
    System.out.println("message received: " + x); 
    } catch (Exception e) { 
     System.out.println("Receiver: " + e); 
     e.printStackTrace(); 
    } 
    } 
} 

應打印:

Starting threads 
Message sent, terminating 
waiting for a message 
message received: 99 

注:核心點是對運行方法中創建ObjectInputStreams。除此之外:刪除不必要的東西(該布爾原語;但添加了試用資源和打印堆棧跟蹤)。

+0

他不需要使用'connect()'。他正在創建一個[連接的PipedInputStream'](https://docs.oracle.com/javase/8/docs/api/java/io/PipedInputStream.html#PipedInputStream-java.io.PipedOutputStream-)。 – EJP

+0

你錯了。它*做*工作,並且我證明了它。你只需要*做對。* – EJP

+0

核心點是在'run()'方法中創建對象流,這是你實際完成的。在重寫的start()方法中創建它們不會比OP的原始代碼更好。 – EJP

2

這些錯誤不是來自對象流。查看堆棧跟蹤。它們來自管道流,並且因爲相關線程已退出或尚未啓動而發生。而原因則是因爲你在線程構造函數中而不是在run()方法中構造對象流,並且兩個對象流構造函數都執行I/O,並且尚未啓動線程。

你不需要睡覺。

請勿使用此管道。使用隊列。

注意您的評論,你不需要投入PipedInputStreamInputStream。它已經是。而事實上你並不是。

+0

@GhostCat根據什麼材料?在創建過程中,兩個管道都被要求執行I/O操作,而沒有另一個正在運行的線程被連接到另一個管道。它不可能工作。嘗試使用在'run()'方法中創建的對象流並親自查看。我做到了。 – EJP