我怎样才能修复我的#34;写死&"并且"读到死亡" ObjectInputStream和ObjectOutputStream的错误?

时间:2017-04-26 17:27:01

标签: java multithreading message-passing

这是my question here的一种扩展。

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

My Sender / Producer类:

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

我的接收者/消费者类:

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或字节。

2 个答案:

答案 0 :(得分:2)

这些错误不是来自对象流。查看堆栈跟踪。它们来自管道流,它们的出现是因为有关线程已经退出或尚未启动。反过来的原因是因为你在线程构造函数中而不是在run()方法中构造对象流,并且两个对象流构造函数都执行I / O,而你还没有启动线程

你不需要睡觉。

不要使用管道。使用队列。

注意你的评论,你不需要将PipedInputStream投射到InputStream。它已经是。事实上,你不是。

答案 1 :(得分:1)

我保持纠正;并遵循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 。除此之外:删除不必要的东西(布尔原语;但添加了资源尝试和打印堆栈跟踪)。