Java 线程通信-Pipe管道流(PipedWriter、PipedReader、PipedOutputStream、PipedInputStream)

说明

Java中的 Pipe 管道是用于 一个虚拟机中的线程之间通信

注意:

  • 一个虚拟机中,也就是一个java程序
  • 不能用于进程之间通信,也就是不能是多个java程序

分类

Java中 Pipe 分为以下类型:

  • 字符流
    • PipedWriter:字符输出流,发送消息
    • PipedReader:字符输入流,接收消息
  • 字节流
    • PipedOutputStream:字节输出流,发送消息
    • PipedInputStream:字节输入流,接收消息

使用

Pipe 管道流的使用方式,与java其他流几乎相同

连接管道

Pipe 管道输出流 可以连接 Pipe 管道输入流

有两种方式:

  • 使用 connect() 方法
  • 通过构造方法

使用 connect() 方法

PipedInputStream pis = new PipedInputStream();

PipedOutputStream pos = new PipedOutputStream();

// 通过输出流的 connect() 连接输入流
pos.connect(pis);

// 通过输入流的 connect() 连接输出流
// 本质还是调用 输出流的 connect()
pis.connect(pos);

通过构造方法

PipedInputStream pis = new PipedInputStream();
// 通过构造方法
PipedOutputStream pos = new PipedOutputStream(pis);

发送数据

在一个线程中,通过 Pipe 管道输出流的 write() 方法发送数据

接收数据

在另一个线程中,通过 Pipe 管道输入流的 read() 方法接收数据

注意

  • 由于 Pipe 管道流是用于 一个虚拟机中的线程之间通信,所以,Pipe 管道输出流 和 Pipe 管道输入流 要在 不同的线程中(在一个虚拟机中)

  • 不要在 一个线程同时 使用管道输入流和管道输出流,会造成 死锁

例子

发送数据线程

package 管道;

import java.io.IOException;
import java.io.PipedReader;
import java.io.PipedWriter;

public class SendThread extends Thread{
    PipedWriter writer = new PipedWriter();

    public void connect(PipedReader pr) throws IOException {
        writer.connect(pr);
    }

    @Override
    public void run() {
        try {
            /*
             由于接收数据时,使用 BufferedReader 的 readLine() 读取一行方法
             所以末尾有 \n 换行符,表示发送一行数据
             */
            writer.write("李雷\n");
            Thread.sleep(100);
            writer.write("韩梅梅\n");
            Thread.sleep(100);
            writer.write("lucy\n");
            Thread.sleep(100);
            writer.write("lili\n");

        } catch (IOException e) {
            throw new RuntimeException(e);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        } finally {
            try {
                writer.close();
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }
    }

    public PipedWriter getWriter() {
        return writer;
    }
}

接收数据线程

package 管道;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.PipedReader;

public class ReceiveThread extends Thread{
    PipedReader reader = new PipedReader();
    BufferedReader br = new BufferedReader(reader);


    @Override
    public void run() {
        while (true){
            try {
                /*
                使用 readLine() 方法读取一行数据,所以发送数据时,末尾要有 \n
                 */
                String s = br.readLine();
                /*
                 管道输出流关闭后,这里接收到数据都是null
                 所以,当接收到null时,就说明管道输出流关闭,就退出接收数据
                 */
                if(s==null){
                    break;
                }
                System.out.println(this.getClass().getSimpleName()+":"+s);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        try {
            br.close();
            reader.close();
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    public PipedReader getReader() {
        return reader;
    }
}

启动类

package 管道;

import java.io.IOException;

public class Main {
    public static void main(String[] args)  {
        SendThread sendThread = new SendThread();
        ReceiveThread receiveThread = new ReceiveThread();
        try {
            // 连接管道
            sendThread.connect(receiveThread.getReader());
        } catch (IOException e) {
            e.printStackTrace();
        }

        sendThread.start();
        receiveThread.start();
    }
}

执行结果:

ReceiveThread:李雷
ReceiveThread:韩梅梅
ReceiveThread:lucy
ReceiveThread:lili

参考:
https://blog.csdn.net/weixin_44671737/article/details/113902971
https://blog.csdn.net/weixin_34154352/article/details/114469098


原文出处:https://malaoshi.top/show_1IX4rlTlJbCf.html