多应用+插件架构,代码干净,二开方便,首家独创一键云编译技术,文档视频完善,免费商用码云13.8K 广告
# Java 线程间通信 – `PipedReader`和`PipedWriter` > 原文: [https://howtodoinjava.com/java/multi-threading/inter-thread-communication-using-piped-streams-in-java/](https://howtodoinjava.com/java/multi-threading/inter-thread-communication-using-piped-streams-in-java/) Java 线程间通信在很长一段时间以来一直是热门的[面试问题](https://howtodoinjava.com/java-interview-questions/)。 在 JDK 1.5 版本中,[`ExecutorService`](https://howtodoinjava.com/java/multi-threading/java-executor-framework-tutorial-and-best-practices/)和[`BlockingQueue`](https://howtodoinjava.com/java/multi-threading/how-to-use-blockingqueue-and-threadpoolexecutor-in-java/)[带来了另一种更有效的实现方式](//howtodoinjava.com/java-5/how-to-use-blockingqueue-and-threadpoolexecutor-in-java/ "How to use BlockingQueue and ThreadPoolExecutor in java"),但管道流方法也值得了解,在某些情况下可能有用。 ```java Table of contents What are piped streams PipedReader and PipedWriter Java inter-thread communication example Summary ``` ## 什么是管道流 **管道流**就像真实的管道一样。 您可以使用某些方法将事物一端放入管道中。 然后,您可以使用其他方法从另一端的管道流中收到相同的信息。 它们以 [**FIFO 顺序**](https://en.wikipedia.org/wiki/FIFO "fifo")的先入先出的方式出现,就像从实际的管道中一样。 ## `PipedReader`和`PipedWriter` [**`PipedReader`**](https://docs.oracle.com/javase/7/docs/api/java/io/PipedReader.html)是[**`Reader`**](https://docs.oracle.com/javase/7/docs/api/java/io/Reader.html "Reader")类的扩展,用于读取字符流。 它的`read()`方法读取连接的`PipedWriter`的流。 同样,[**`PipedWriter`**](https://docs.oracle.com/javase/7/docs/api/java/io/PipedWriter.html) 是`Writer`类的扩展,它执行`Reader`类所收缩的所有工作。 可以通过以下两种方法将作家连接到读者: 1. 使用构造器`PipedWriter(PipedReader pr)` 2. 使用`connect(PipedReader pr)`方法 通过上述任何一种方式连接后,任何线程都可以使用`write(....)`方法在流中写入数据,并且数据将可供读取器使用,并且可以使用`read()`方法进行读取。 ## Java 线程间通信示例 下面给出的 Java 程序创建两个线程。 一个线程负责写入流,第二个线程仅读取数据以在控制台中打印它们。 ```java public class PipeReaderThread implements Runnable { PipedReader pr; String name = null; public PipeReaderThread(String name, PipedReader pr) { this.name = name; this.pr = pr; } 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); } } } ``` ```java public class PipeWriterThread implements Runnable { PipedWriter pw; String name = null; public PipeWriterThread(String name, PipedWriter pw) { this.name = name; this.pw = pw; } 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); } } } ``` ```java package multiThread; import java.io.*; public class PipedCommunicationTest { public static void main(String[] args) { new PipedCommunicationTest(); } public PipedCommunicationTest() { try { // Create writer and reader instances PipedReader pr = new PipedReader(); PipedWriter pw = new PipedWriter(); // Connect the writer with reader pw.connect(pr); // Create one writer thread and one reader thread Thread thread1 = new Thread(new PipeReaderThread("ReaderThread", pr)); Thread thread2 = new Thread(new PipeWriterThread("WriterThread", pw)); // start both threads thread1.start(); thread2.start(); } catch (Exception e) { System.out.println("PipeThread Exception: " + e); } } } ``` 程序输出: ```java Testing data written... Testing data written... Testing data written... ``` ## 总结 * 您必须先创建某种类型的读取器并将其连接,然后才能写入管道。 换句话说,两个端必须存在并且已经连接,以使写入端正常工作。 * 完成写入管道后,您将无法切换到最初未连接管道的其他读取器。 * 如果关闭阅读器,则无法从管道中读回。 但是,您可以成功关闭写入端,并且仍然可以从管道读取数据。 * 如果写入管道的线程结束,则无法从管道读回。 学习愉快!