首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Java IO学习笔记五

Java IO学习笔记五

作者头像
爱撒谎的男孩
发布2019-12-31 11:25:38
3090
发布2019-12-31 11:25:38
举报
文章被收录于专栏:码猿技术专栏码猿技术专栏

文章目录

  1. 1. 管道流
    1. 1.1. PipedOutputStream
      1. 1.1.1. 构造函数
      2. 1.1.2. 常用函数
    2. 1.2. PipedInputStream
      1. 1.2.1. 构造函数
      2. 1.2.2. 常用函数
    3. 1.3. 实例
    4. 1.4. 问题
    5. 1.5. 解决方法
    6. 1.6. 参考文章

管道流

  • 管道流的主要作用是可以进行两个线程间的通讯,分为管道输出流(PipedOutputStream)、管道输入流(PipedInputStream),如果想要进行管道输出,则必须要把输出流连在输入流之上,在PipedOutputStream类上有如下的一个方法用于连接管道: public void connect(PipedInputStream snk)throws IOException
  • 通常是创建两个单独的线程来实现通信,如果是单个线程的话容易出现线程堵塞,因为输出流最多只能向缓冲区写入1024个字节的数据,如果超出就会出现线程堵塞,因此必须创建多个线程实现缓冲区的释放和存储

PipedOutputStream

  • 管道输出流是管道的发送端,可以将管道输出流连接到管道输入流来创建一个通信管道,通常,数据由某个线程写入 PipedOutputStream对象,并由其他线程从连接的 PipedInputStream 读取。不建议对这两个对象尝试使用单个线程,因为这样可能会造成该线程死锁。如果某个线程正从连接的管道输入流中读取数据字节,但该线程不再处于活动状态,则该管道被视为处于 毁坏 状态。

构造函数

  • PipedOutputStream() 创建尚未连接到管道输入流的管道输出流。
  • PipedOutputStream(PipedInputStream snk) 创建连接到指定管道输入流的管道输出流。

常用函数

  • close() 关闭
  • void connect(PipedInputStream snk) 将此管道输出流连接到接收者。
  • void flush() 刷新此输出流并强制写出所有缓冲的输出字节。
  • void write(byte[] b, int off, int len)len 字节从初始偏移量为 off 的指定 byte 数组写入该管道输出流。
  • void write(int b) 将指定 byte 写入传送的输出流。

PipedInputStream

  • 管道输入流应该连接到管道输出流;管道输入流提供要写入管道输出流的所有数据字节。通常,数据由某个线程从 PipedInputStream 对象读取,并由其他线程将其写入到相应的 PipedOutputStream。不建议对这两个对象尝试使用单个线程,因为这样可能死锁线程。管道输入流包含一个缓冲区,可在缓冲区限定的范围内将读操作和写操作分离开。 如果向连接管道输出流提供数据字节的线程不再存在,则认为该管道已损坏。

构造函数

  • PipedInputStream() 创建尚未连接的 PipedInputStream
  • PipedInputStream(PipedOutputStream src) 创建 PipedInputStream,使其连接到管道输出流 src

常用函数

  • int available() 返回可以不受阻塞地从此输入流中读取的字节数。
  • void close() 关闭此管道输入流并释放与该流相关的所有系统资源。
  • void connect(PipedOutputStream src) 使此管道输入流连接到管道输出流 src
  • int read() 读取此管道输入流中的下一个数据字节。
  • int read(byte[] b, int off, int len) 将最多 len 个数据字节从此管道输入流读入 byte 数组。
  • protected void receive(int b) 接收数据字节。

实例

package IO;
import java.io.IOException;
import java.io.PipedInputStream;
import java.io.PipedOutputStream;
/**
 * Created by chenjiabing on 17-5-25.
 */
/**
 * 注意的问题:
 * 1.写线程正在往缓冲区写数据的时候,但是此时的读线程的管道结束,那么此时的写线程的管道就会发生IOException异常
 * 2.读线程正在从缓冲区读数据的时候,但是此时的写线程的管道已经结束了,此时就会引起读线程的管道发生IOException异常
 * 3.必须是启用多线程才能实现管道之间的读写,否则会出现堵塞现象,因为这里的PipeOutputStream每次向缓冲区写入的字节数最大是1024,如果不及时的减少缓冲区的数据量就会出现堵塞
 */
public class demo7 {
    public static PipedOutputStream outputStream = new PipedOutputStream();
    public static PipedInputStream inputStream = new PipedInputStream();
    /**
     * 创建一个写入数据进程,使用的是PipeOutStream,将数据写入管道中
     */
    public static void send() {
        new Thread(new Runnable() {
            @Override
            public void run() {
                byte[] bytes = new byte[2000];     //创建一个2000字节的数组
                while (true) {
                    try {
                        outputStream.write(bytes, 0, 2000);  //写入管道,但是这里的缓冲区最多写入1024个字节的数据,因此这个是一次没有写完
                        System.out.println("写入成功");
                    } catch (IOException e) {
                        System.out.println("写入失败");
                        System.exit(1);
                    }
                }
            }
        }).start();
    }
    /**
     * 使用PipeInputStream创建一个读取的线程
     */
    public static void receive() {
        new Thread(new Runnable() {
            @Override
            public void run() {
                byte[] bytes = new byte[100];  //一次性只读取100个字节
                int len = 0;
                try {
                    len = inputStream.read(bytes, 0, 100);  //读取
                    while (len != -1) {
                        System.out.println("已经读取了" + len + "个字节");
                        len = inputStream.read(bytes, 0, 100);
                    }
                } catch (IOException e) {
                    System.out.println("读取失败");
                    System.exit(1);
                }
            }
        }).start();
    }
    public static void main(String args[]) {
        try {
            inputStream.connect(outputStream);  //连接
        } catch (IOException e) {
            System.out.println("连接失败");
            System.exit(1);
        }
        send();
        receive();
    }
}

注意:从上面的运行结果可以看出,缓冲区最多可以写入1024个字节的数据,所以在缓冲区满了之后上面的send进程就会堵塞等待缓冲区空闲,如果recieve进程不继续读取数据了,那么就会一直出现堵塞

问题

  • 写线程正在往缓冲区写数据的时候,但是此时的读线程的结束读取,那么此时的写线程的管道就会发生IOException异常,可以将上面receive进程中的while(true)去掉就可以清楚的看出
  • 读线程正在从缓冲区读数据的时候,但是此时的写线程的管道已经结束了,此时就会引起读线程的管道发生IOException异常,将上面的send进程中的while(true)去掉就可以实现这个问题
  • 必须是启用多线程才能实现管道之间的读写,否则会出现堵塞现象,因为这里的PipeOutputStream每次向缓冲区写入的字节数最大是1024,如果不及时的减少缓冲区的数据量就会出现堵塞

解决方法

  • 后续更新中……….

参考文章

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2017-05-25,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 管道流
    • PipedOutputStream
      • 构造函数
      • 常用函数
    • PipedInputStream
      • 构造函数
      • 常用函数
    • 实例
      • 问题
        • 解决方法
          • 参考文章
          领券
          问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档