管道流Piped Streams

管道流(Piped Streams)这个话题长期以来一直是一个热门的面试问题。JDK 1.5的发布,ExecutorService和BlockingQueue带来的做法更有效,但这种方法也值得了解的,可能在某些情况下是有用的。

什么是管道流

管道流就像真正的水管道,你用一些方法将东西放在管道的一端,然后在管道的另一端使用其他方法接收相同的内容。它们是以先进先出的顺序出来的,就像是从真正的管道中出来的。

PipedReader和PipedWriter

PipedReader类是继承自Reader类(用于字符流的读取),它的read()方法读取连接的PipedWriter的流。同样的,PipedWriter类是继承Writer类,用于做所有与Reader类连接相关的事情。

PipedWriter可以通过以下2个方法与PipedReader连接:

  1. 使用构造函数PipedWriter(PipedReader pr)
  2. 使用connect(PipedReader pr) 方法
    通过以上方式,一旦连接,任何线程都可以使用write(…)方法写入数据流和使用read()读取数据。

运行例子

在给定的示例程序下面创建两个线程。一个线程负责写入流,第二个线程只读取数据以在控制台中打印它们。

public class PipedCommunicationTest {
    public PipedCommunicationTest() {
        try {
            PipedReader pr = new PipedReader();
            PipedWriter pw = new PipedWriter();
            pw.connect(pr);

            Thread thread1 = new Thread(
                    new PipeReaderThread("ReaderThread", pr));
            Thread thread2 = new Thread(
                    new PipeWriterThread("WriterThread", pw));
            // start both threads
            thread1.start();
            thread2.start();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    class PipeReaderThread implements Runnable {
        String name = null;
        PipedReader pr;

        public PipeReaderThread(String name, PipedReader pr) {
            this.name = name;
            this.pr = pr;
        }

        @Override
        public void run() {
            try {
                // continuously read data from stream and print it in console
                while (true) {
                    char c = (char) pr.read(); // read a char
                    if (c != -1) { // check for -1 indicating end of file
                        System.out.print(c);
                    }
                }
            } catch (Exception e) {
                System.out.println(" PipeThread Exception: " + e);
            }
        }
    }

    class PipeWriterThread implements Runnable {
        String name = null;
        PipedWriter pw;

        public PipeWriterThread(String name, PipedWriter pw) {
            this.name = name;
            this.pw = pw;
        }

        @Override
        public void run() {
            try {
                while (true) {
                    // Write some data after every two seconds
                    pw.write("Testing data written...\n");
                    pw.flush();
                    Thread.sleep(2000);
                }
            } catch (Exception e) {
                System.out.println(" PipeThread Exception: " + e);
            }
        }
    }

    public static void main(String[] args) {
        new PipedCommunicationTest();
    }
}

重点

  • 如果不创建某种类型的读取器并连接到它,就无法写入管道。换言之,两端必须存在并已经连接,以便写入结束工作。
  • 当您完成对管道的写入时,您不能切换到另一个管道(未连接的读取器)。
  • 如果关闭读取器,则无法从管道读取。然而,您可以成功地关闭写入结束,并且仍然从管道读取。
  • 如果写入线程的线程结束,则无法从管道中读取。

参考
Java Inter-thread Communication using Piped Streams

你可能感兴趣的:(管道流Piped Streams)