当前位置: 代码迷 >> 综合 >> Java IO (5) -- PipedOutputStream 类 PipedInputStream 类
  详细解决方案

Java IO (5) -- PipedOutputStream 类 PipedInputStream 类

热度:34   发布时间:2023-12-16 13:27:15.0

文章目录

    • 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

  1. private PipedInputStream sink:与管道输出流连接的管道输入流

2. PipedInputStream

  1. 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

  1. public PipedOutputStream(PipedInputStream snk) throws IOException{ connect(snk) }:传入PipedInputStream,创建连接到指定管道输入流的管道输出流
  2. public PipedOutputStream():创建了未连接到管道输入流的管道输出流

2. PipedInputStream

  1. public PipedInputStream(PipedOutputStream src) throws IOException:创建管道输入流,并连接到管道输出流src
  2. public PipedInputStream(PipedOutputStream src, int pipeSize):创建管道出入流,并连接到管道输出流src,并创建指定大小pipeSize的缓冲区
  3. public PipedInputStream():创建无连接的管道输入流
  4. public PipedInputStream(int pipeSize):创建无连接的管道输入流,并创建指定大小PipeSize缓冲区

2. 其他方法

1. PipedOutputStream

  1. public synchronized void connect(PipedInputStream snk) throws IOException:将管道输入流和管道输出流连接
  2. public void write(int b) throws IOException:将一个字节b写入到缓冲区
  3. public void write(byte b[], int off, int len) throws IOException:将字节数组b的off索引开始,长度为len个字节写入到缓冲区中
  4. public synchronized void flush() throws IOException:刷新缓冲
  5. public void close() throws IOException:关闭管道输出流,释放相关资源,并且流不能再写入字节

2. PipedInputStream

  1. public void connect(PipedOutputStream src) throws IOException:将管道输入流连接到管道输出流
  2. protected synchronized void receive(int b) throws IOException:从管道输出流中接受一个字节b存储到缓冲区
  3. synchronized void receive(byte b[], int off, int len) throws IOException:从管道输出流中接受字节数组b中,索引off开始,长度为len的字节
  4. public synchronized int read(byte b[], int off, int len) throws IOException:将缓冲区的字节读取到字节数组b中索引off开始,长度为len之间的位置.最多为len个字节
  5. public synchronized int read() throws IOException:从缓冲区读取一个字节
  6. public synchronized int available() throws IOException:缓冲区中可读取的字节数
  7. 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. 扩展

  1. 管道输出流先向缓冲区里面写入800个字节,读取线程读取100个字节.此时out<in,剩余可读取的字节数为in-out
    在这里插入图片描述
  2. 然后又向缓冲区里面写入424个字节.此时out<in,可读取的字节数为buffer.length-out或者in-out
    在这里插入图片描述
  3. 再次循环写入100个字节,此时in==out表示,缓冲区数据已经满了,等待读取线程读取数据
    在这里插入图片描述
  4. 然后读取线程读取了700个字节,那么此时out>in,此时可读取的字节数为in+(buffer.length-out)
    在这里插入图片描述
  相关解决方案