Java 管道原理
如上图 : 线程A 将数据写入到 管道中, 这个管道是一个缓冲区, 我的理解是就像是一个文件, 线程A 将数据写入到这个文件(管道)中, 而线程 B 从这个文件中读取数据 ,这样就实现了进程间的通信
Java 管道的一些特点
-
管道流是单向的, 只能由 输出流 -> 管道 -> 输入流
-
管道中的数据一旦被读取就会从管道中丢弃, 释放空间以便于写入更多的数据
-
如果在向管道缓冲区的数据已经满的时候, 写入数据的 Write 方法会自动被阻塞, 等待缓冲区数据被读取有空闲的空间的时候才会继续向管道中写入数据, 同样的, 从管道读取数据的时候 当管道为空的时候,读取数据的read方法也会被阻塞,等待管道中有数据的时候才会继续读取
-
管道的输入输出流 任何一个提前关闭 都不会影响到另外一个流,
-
注意:管道输出流输出结束后一定要关闭输出流,因为只有关闭输出流之后,对端输入流read()才能返回null,如果没有关闭输出流
会报错 : java.io.IOException: Write end dead
Java 管道的Demo
package com.wangt.juc.thread.communication;
import java.io.*;
/**
* @author 王天赐
* @create 2019-11-02 15:53
*/
public class ThreadCommunicationByPipe {
// 读线程
public static class ReadThread implements Runnable{
private PipedInputStream pis = null;
private String lines = "";
// 获取 管道输入流
public PipedInputStream getPis(){
pis = new PipedInputStream();
return pis;
}
@Override
public void run() {
// 将管道输入流转换为缓冲流
BufferedReader br = new BufferedReader(new InputStreamReader(pis));
System.out.println("Read 线程开启 开始读入数据.... ");
try {
while((lines = br.readLine()) != null){
// 打印输入的数据
System.out.println("read : " + lines);
}
br.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
// 写线程
public static class WriteThread implements Runnable{
private PipedOutputStream pos = null;
// 获取管道输出流
public PipedOutputStream getPos() {
pos = new PipedOutputStream();
return pos;
}
@Override
public void run() {
long time = System.currentTimeMillis();
System.out.println("Write 线程开启 开始写数据.... ");
PrintStream ps = new PrintStream(pos);
for (int i = 0; i < 10; i++) {
ps.println("假面骑士 " + i + " 号");
ps.flush();
}
// 注意 : 这里不关闭 会报错 : java.io.IOException: Write end dead
ps.close();
}
}
public static void main(String[] args) throws IOException {
WriteThread write = new WriteThread();
ReadThread read = new ReadThread();
// 连接 输入和输出管道流
// 注意 : 管道只能是单向通信, 如果想双向 需要创建两个管道
write.getPos().connect(read.getPis());
// 开启线程
new Thread(write).start();
new Thread(read).start();
}
}