一、java管道流介绍
在java多线程通信中管道通信是一种重要的通信方式,在java中我们通过配套使用管道输出流PipedOutputStream和管道输入流PipedInputStream完成线程间通信。多线程管道通信的主要流程是在一个线程中向PipedOutputStream写入数据,这些数据会自动传送到对应的管道输入流PipedInputStream中,其他线程通过读取PipeInputStream中缓冲的数据实现多线程间通信。
二、PipedInputStream
1 - PipedInputStream介绍
PipeInputStream是管道输入流,继承自InputStream,连接到一个管道输出流PipedOutputStream。可以缓存连接的管道输出流PipedOutputStream写入的字节数据。通常在一个线程使用PipedInputStream读取数据,在其他线程使用PipedOutputStream写入字节数据。不推荐在一个线程中使用PipedInputStream和PipedOutputStream可能会在线程中造成死锁,管道输入流包含一个缓冲区buff用于读操作和写操作。
2 - PipeInputStream源码分析
1)成员变量
package java.io;
public class PipedInputStream extends InputStream {
//管道输出流是否关闭标记
boolean closedByWriter = false;
//管道输入流是否标记
volatile boolean closedByReader = false;
//管道输入流与管道输出流是否建立连接
boolean connected = false;
//读取“管道”数据即PipedInputStream线程
Thread readSide;
//向管道写入数据即PipedOutputStream线程
Thread writeSide;
//管道默认大小
private static final int DEFAULT_PIPE_SIZE = 1024;
protected static final int PIPE_SIZE = DEFAULT_PIPE_SIZE;
// 缓冲区
protected byte buffer[];
//下一个写入字节的位置
protected int in = -1;
//下一个读取字节的位置。若out==in说明管道输出流写入的数据全部被读取
protected int out = 0;
}
2)构造方法
public PipedInputStream(PipedOutputStream src) throws IOException {
this(src, DEFAULT_PIPE_SIZE);
}
public PipedInputStream(PipedOutputStream src, int pipeSize)
throws IOException {
initPipe(pipeSize);
connect(src);
}
public PipedInputStream() {
initPipe(DEFAULT_PIPE_SIZE);
}
从源码我们可以知道管道输入流PipedInputStream构造方法做了两件事,按照指定大小pipeSize初始化缓冲区,如果还指定了关联的管道输出流PipedOutputStream,那么调用connect方法连接它。如果指定的pipeSize小于等于0那么抛出IllegalArgumentException异常,如果当前的管道输入流已经和指定的管道输出流建立连接那么抛出IOException异常提示连接已经建立。
3)其他成员方法