原文: https://howtodoinjava.com/java/multi-threading/inter-thread-communication-using-piped-streams-in-java/

Java 线程间通信在很长一段时间以来一直是热门的面试问题。 在 JDK 1.5 版本中,ExecutorServiceBlockingQueue带来了另一种更有效的实现方式,但管道流方法也值得了解,在某些情况下可能有用。

  1. Table of contents
  2. What are piped streams
  3. PipedReader and PipedWriter
  4. Java inter-thread communication example
  5. Summary

什么是管道流

管道流就像真实的管道一样。 您可以使用某些方法将事物一端放入管道中。 然后,您可以使用其他方法从另一端的管道流中收到相同的信息。

它们以 FIFO 顺序的先入先出的方式出现,就像从实际的管道中一样。

PipedReaderPipedWriter

PipedReaderReader类的扩展,用于读取字符流。 它的read()方法读取连接的PipedWriter的流。 同样,PipedWriterWriter类的扩展,它执行Reader类所收缩的所有工作。

可以通过以下两种方法将作家连接到读者:

  1. 使用构造器PipedWriter(PipedReader pr)
  2. 使用connect(PipedReader pr)方法

通过上述任何一种方式连接后,任何线程都可以使用write(....)方法在流中写入数据,并且数据将可供读取器使用,并且可以使用read()方法进行读取。

Java 线程间通信示例

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

  1. public class PipeReaderThread implements Runnable
  2. {
  3. PipedReader pr;
  4. String name = null;
  5. public PipeReaderThread(String name, PipedReader pr)
  6. {
  7. this.name = name;
  8. this.pr = pr;
  9. }
  10. public void run()
  11. {
  12. try {
  13. // continuously read data from stream and print it in console
  14. while (true) {
  15. char c = (char) pr.read(); // read a char
  16. if (c != -1) { // check for -1 indicating end of file
  17. System.out.print(c);
  18. }
  19. }
  20. } catch (Exception e) {
  21. System.out.println(" PipeThread Exception: " + e);
  22. }
  23. }
  24. }
  1. public class PipeWriterThread implements Runnable
  2. {
  3. PipedWriter pw;
  4. String name = null;
  5. public PipeWriterThread(String name, PipedWriter pw) {
  6. this.name = name;
  7. this.pw = pw;
  8. }
  9. public void run() {
  10. try {
  11. while (true) {
  12. // Write some data after every two seconds
  13. pw.write("Testing data written...n");
  14. pw.flush();
  15. Thread.sleep(2000);
  16. }
  17. } catch (Exception e) {
  18. System.out.println(" PipeThread Exception: " + e);
  19. }
  20. }
  21. }
  1. package multiThread;
  2. import java.io.*;
  3. public class PipedCommunicationTest
  4. {
  5. public static void main(String[] args)
  6. {
  7. new PipedCommunicationTest();
  8. }
  9. public PipedCommunicationTest()
  10. {
  11. try
  12. {
  13. // Create writer and reader instances
  14. PipedReader pr = new PipedReader();
  15. PipedWriter pw = new PipedWriter();
  16. // Connect the writer with reader
  17. pw.connect(pr);
  18. // Create one writer thread and one reader thread
  19. Thread thread1 = new Thread(new PipeReaderThread("ReaderThread", pr));
  20. Thread thread2 = new Thread(new PipeWriterThread("WriterThread", pw));
  21. // start both threads
  22. thread1.start();
  23. thread2.start();
  24. }
  25. catch (Exception e)
  26. {
  27. System.out.println("PipeThread Exception: " + e);
  28. }
  29. }
  30. }

程序输出:

  1. Testing data written...
  2. Testing data written...
  3. Testing data written...

总结

  • 您必须先创建某种类型的读取器并将其连接,然后才能写入管道。 换句话说,两个端必须存在并且已经连接,以使写入端正常工作。
  • 完成写入管道后,您将无法切换到最初未连接管道的其他读取器。
  • 如果关闭阅读器,则无法从管道中读回。 但是,您可以成功关闭写入端,并且仍然可以从管道读取数据。
  • 如果写入管道的线程结束,则无法从管道读回。

学习愉快!