Search code examples
javamultithreadingmessage-passing

How can I fix my "write end dead" and "read end dead" errors for ObjectInputStream and ObjectOutputStream?


This is a kind of an extension of my question here.

I have 3 classes.

My main:

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);}
    }
}

My Sender/Producer class:

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);}
    }
}

My Receiver/Consumer class:

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);}

    }
}

Produces this output:

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

I read in this page that I'm getting these exceptions because I wasn't closing the pipes. But even if I do, I still get them. How can I fix this?

edit: the reason I'm casting the type of the stream objects from, say, PipedInputStream to InputStream and then constructing a new ObjectInputStream using InputStream is because I want to be able to send and receive data of various types, not just int or bytes.


Solution

  • I stay corrected; and following the advise by EJP; here is a working solution.

    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();
        }
      }
    }
    

    Should print:

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

    Notes: the core point is to create the ObjectInputStreams within the run methods. Beyond that: removed the things not necessary (that boolean primitive; but added try-with-resources and printing stack traces).