如何使用管道将数据从多个线程发送到单个接收线程?

时间:2017-04-28 03:50:43

标签: java multithreading

我有3节课;主要,接收者和发送者类。

主:

// imports...
public class Main {
    public static void main (String argv[]) {
        try {
            PipedOutputStream pos = new PipedOutputStream();
            PipedInputStream pis = new PipedInputStream(pos);

            Semaphore sem = new Semaphore(0);

            Test1 t1 = new Test1(pos, true);
            t1.setName("writer1");
            Test1 t2 = new Test1(pos, false);
            t2.setName("write2");
            Test2 r = new Test2(pis);

            System.out.println("starting");
            r.start();
            t1.start();
            t2.start();
        } catch (Exception e) {System.out.println(e);}
    }
}

发信人:

//imports...
public class Test1 extends Thread {

    PipedOutputStream pos;

    public Test1 (PipedOutputStream pos) {
        this.pos = pos;
    }

    public void run() {
        try {
            ObjectOutputStream oos = new ObjectOutputStream(pos);
            while (true) {
                System.out.println("writing");
                oos.writeUTF(Thread.currentThread().getName());
                Thread.sleep(1000);
                System.out.println("flushing");
                oos.flush();
            }
        } catch (Exception e) {e.printStackTrace();}
    }
}

我的接收者:

public class Test2 extends Thread {

    PipedInputStream pis;

    public Test2 (PipedInputStream pis) {
        this.pis = pis;
    }

    public void run() {
        try {
            ObjectInputStream ois = new ObjectInputStream(pis);
            while (true) {
                System.out.println("receiving");
                String s = ois.readUTF();
                System.out.println("received from " + s);
            }
        } catch (Exception e) {e.printStackTrace();}
    }
}

运行此命令会使程序崩溃,并显示以下错误报告:

starting
writing
writing
receiving
java.io.StreamCorruptedException: invalid type code: AC
    at     java.io.ObjectInputStream$BlockDataInputStream.readBlockHeader(Unknown Source)
    at java.io.ObjectInputStream$BlockDataInputStream.refill(Unknown Source)
    at java.io.ObjectInputStream$BlockDataInputStream.read(Unknown Source)
    at java.io.DataInputStream.readUnsignedShort(Unknown Source)
    at     java.io.ObjectInputStream$BlockDataInputStream.readUnsignedShort(Unknown Source)
    at java.io.ObjectInputStream$BlockDataInputStream.readUTF(Unknown Source)
    at java.io.ObjectInputStream.readUTF(Unknown Source)
    at Test2.run(Test2.java:18)
flushing
flushing
java.io.IOException: Read end dead
    at java.io.PipedInputStream.checkStateForReceive(Unknown Source)
    at java.io.PipedInputStream.receive(Unknown Source)
    at java.io.PipedOutputStream.write(Unknown Source)
    at     java.io.ObjectOutputStream$BlockDataOutputStream.writeBlockHeader(Unknown Source)
    at java.io.ObjectOutputStream$BlockDataOutputStream.drain(Unknown Source)
    at java.io.ObjectOutputStream$BlockDataOutputStream.flush(Unknown Source)
    at java.io.ObjectOutputStream.flush(Unknown Source)
    at Test1.run(Test1.java:23)
java.io.IOException: Read end dead
    at java.io.PipedInputStream.checkStateForReceive(Unknown Source)
    at java.io.PipedInputStream.receive(Unknown Source)
    at java.io.PipedOutputStream.write(Unknown Source)
    at     java.io.ObjectOutputStream$BlockDataOutputStream.writeBlockHeader(Unknown Source)
    at java.io.ObjectOutputStream$BlockDataOutputStream.drain(Unknown Source)
    at java.io.ObjectOutputStream$BlockDataOutputStream.flush(Unknown Source)
    at java.io.ObjectOutputStream.flush(Unknown Source)
    at Test1.run(Test1.java:23)

以下是我尝试使用此设置时学到的一些内容:

  • 如果我在Main类中注释掉其中一个发送方线程,那么通信将变为一对一(而不是两个发送方与一个接收方)并且功能没有任何问题。
  • 我假设错误是由于在接收线程读取发送的第一个数据项之前通过管道刷新多个数据项,因此以某种方式“破坏”流,这将解释{{1 }}。事实并非如此 - 即使我确保使用可保证一个线程的同步方案,一旦接收器线程尝试从流(StreamCorruptedException)读取,StreamCorruptedException就会被抛出在发送之前等待,直到接收器读取(并清除流)之前发送的任何数据。

据我所知,任何多个发送方线程发送到同一个接收方线程的情况最终会被String s = ois.readUTF();抛出。

我的问题是:如何使用管道/ StreamCorruptedException / ObjectOutputStream从多个线程发送到单个接收线程?

0 个答案:

没有答案