文章目录
-
- 1. 概念
- 2. 字段
-
- 1. PipedOutputStream
- 2. PipedInputStream
- 3. 方法
-
- 1. 构造器
-
- 1. PipedOutputStream
- 2. PipedInputStream
- 2. 其他方法
-
- 1. PipedOutputStream
- 2. PipedInputStream
- 4. 案例
- 5. 扩展
1. 概念
PipedOutputStream和PipedInputStream分别是管道输出流和管道输入流,是字节流的一种。两者配合使用可以进行同一个进程不同线程之间的通信,管道输入流用于向管道中读取数据,管道输出流用于向管道中写入数据。通常管道输入流和管道输出流在不同的线程中,如果在同一个线程可能存在死锁的情况。
实现方式大致是,管道输出流与管道输出流进行关联,当一个线程向管道输出流中写入数据,实际上是将数据写到与管道输出关联的管道输入流的缓冲区中(大小为1024的字节数组),其他线程通过管道输入流读取到缓冲区中的数据,这样就是实现了线程之间的通信。而当缓冲区中的数据已经为满的情况下,管道输出流将阻塞,当缓冲区中的数据为空的情况下,管道输入流将阻塞。
2. 字段
1. PipedOutputStream
- private PipedInputStream sink:与管道输出流连接的管道输入流
2. PipedInputStream
- protected static final int PIPE_SIZE = DEFAULT_PIPE_SIZE:默认创建的缓冲区的大小为1024字节
protected byte buffer[]:缓冲区
protected int in = -1:缓冲区的索引,从管道输出流中接受到的字节存储到此位置
protected int out = 0:缓冲区的索引,管道输入流读取的下一个字节的位置
3. 方法
1. 构造器
1. PipedOutputStream
- public PipedOutputStream(PipedInputStream snk) throws IOException{ connect(snk) }:传入PipedInputStream,创建连接到指定管道输入流的管道输出流
- public PipedOutputStream():创建了未连接到管道输入流的管道输出流
2. PipedInputStream
- public PipedInputStream(PipedOutputStream src) throws IOException:创建管道输入流,并连接到管道输出流src
- public PipedInputStream(PipedOutputStream src, int pipeSize):创建管道出入流,并连接到管道输出流src,并创建指定大小pipeSize的缓冲区
- public PipedInputStream():创建无连接的管道输入流
- public PipedInputStream(int pipeSize):创建无连接的管道输入流,并创建指定大小PipeSize缓冲区
2. 其他方法
1. PipedOutputStream
- public synchronized void connect(PipedInputStream snk) throws IOException:将管道输入流和管道输出流连接
- public void write(int b) throws IOException:将一个字节b写入到缓冲区
- public void write(byte b[], int off, int len) throws IOException:将字节数组b的off索引开始,长度为len个字节写入到缓冲区中
- public synchronized void flush() throws IOException:刷新缓冲
- public void close() throws IOException:关闭管道输出流,释放相关资源,并且流不能再写入字节
2. PipedInputStream
- public void connect(PipedOutputStream src) throws IOException:将管道输入流连接到管道输出流
- protected synchronized void receive(int b) throws IOException:从管道输出流中接受一个字节b存储到缓冲区
- synchronized void receive(byte b[], int off, int len) throws IOException:从管道输出流中接受字节数组b中,索引off开始,长度为len的字节
- public synchronized int read(byte b[], int off, int len) throws IOException:将缓冲区的字节读取到字节数组b中索引off开始,长度为len之间的位置.最多为len个字节
- public synchronized int read() throws IOException:从缓冲区读取一个字节
- public synchronized int available() throws IOException:缓冲区中可读取的字节数
- public void close() throws IOException:关闭管道输入流,并释放相关资源
4. 案例
public class Sender extends Thread {
private PipedOutputStream out = new PipedOutputStream();public PipedOutputStream getOutputStream() {
return out;}public void run() {
try {
String message = "The Demo is about PipedOutputStream and PipedInputStream";out.write(message.getBytes());out.close();}catch(IOException e) {
e.printStackTrace();}}
}
public class Receiver extends Thread {
private PipedInputStream in = new PipedInputStream();public PipedInputStream getPipedInputStream() {
return in;}public void run() {
try {
byte[] buffer = new byte[1024];int len = in.read(buffer);System.out.println(new String(buffer, 0, len));in.close();} catch (IOException e) {
e.printStackTrace();}}
}
public class PipedDemo {
public static void main(String[] args) {
Sender sender = new Sender();Receiver receiver = new Receiver();PipedOutputStream pops = sender.getOutputStream();PipedInputStream pips = receiver.getPipedInputStream();try {
//管道流连接,与注释的语句相同pops.connect(pips);//pips.connect(pops);//开始两个线程,一个管道输入流用于读取数据,一个是管道输出流写入数据sender.start();receiver.start();} catch (IOException e) {
e.printStackTrace();}}
}//结果
The Demo is about PipedOutputStream and PipedInputStream
5. 扩展
- 管道输出流先向缓冲区里面写入800个字节,读取线程读取100个字节.此时out<in,剩余可读取的字节数为in-out
- 然后又向缓冲区里面写入424个字节.此时out<in,可读取的字节数为buffer.length-out或者in-out
- 再次循环写入100个字节,此时in==out表示,缓冲区数据已经满了,等待读取线程读取数据
- 然后读取线程读取了700个字节,那么此时out>in,此时可读取的字节数为in+(buffer.length-out)