Java IO:PipedOutputStream和PipedInputStream使用详解及源码分析
来源:互联网 发布:devcpp使用教程c语言 编辑:程序博客网 时间:2024/04/29 01:41
1 使用方法
PipedOutputStream和PipedInputStream是管道输出流和管道输入流,配合使用可以实现线程间通信。
使用管道实现线程间通信的主要流程如下:建立输出流out和输入流in,将out和in绑定,out中写入的数据则会同步写入的in的缓冲区(实际情况是,out中写入数据就是往in的缓冲区写数据,out中没有数据缓冲区)。
1.1 方法介绍
PipedOutputStream提供的API如下:
//构造函数public PipedOutputStream(PipedInputStream snk);public PipedOutputStream();public synchronized void connect(PipedInputStream snk); //将PipedOutputStream 和 PipedInputSteam绑定public void write(int b); //向output写入bpublic void write(byte b[], int off, int len); //向output写入字节数组bpublic synchronized void flush();//刷新缓冲区,通知其他input读取数据public void close();// 关闭PipedOutputStream提供的API如下://构造函数public PipedInputStream(PipedOutputStream src);public PipedInputStream(PipedOutputStream src, int pipeSize);public void connect(PipedOutputStream src); //将PipedOutputStream 和 PipedInputSteam绑定protected synchronized void receive(int b); //向input缓冲区写入bsynchronized void receive(byte b[], int off, int len); //向input写入字节数组bpublic synchronized int read(); //读取缓冲区下一个字节public synchronized int read(byte b[], int off, int len) //读取缓冲区字节数组到bpublic synchronized int available();// 缓冲区可读字节数组的个数public void close(); // 关闭
1.2 使用示例
/** * 生产者线程 */public class Producer extends Thread { //输出流 private PipedOutputStream out = new PipedOutputStream(); //构造方法 public Producer(PipedOutputStream out) { this.out = out; } @Override public void run() { writeMessage(); } private void writeMessage() { StringBuilder sb = new StringBuilder("Hello World!!!"); try { out.write(sb.toString().getBytes()); out.close(); } catch (IOException e) { e.printStackTrace(); } }}/** * 消费线程 */public class Consumer extends Thread { //输入流, 默认缓冲区大小为1024 private PipedInputStream in = new PipedInputStream(); //构造方法 public Consumer(PipedInputStream in) { this.in = in; } @Override public void run() { readMessage(); } private void readMessage() { byte [] buf = new byte[1024]; try { int len = in.read(buf); System.out.println("缓冲区的内容为: " + new String(buf, 0, len)); in.close(); } catch (IOException e) { e.printStackTrace(); } finally { } }}@org.junit.Testpublic void testPiped() { /** * 流程 * 1 建立输入输出流 * 2 绑定输入输出流 * 3 向缓冲区写数据 * 4 读取缓冲区数据 */ PipedOutputStream out = new PipedOutputStream(); PipedInputStream in = new PipedInputStream(); Producer producer = new Producer(out); Consumer consumer = new Consumer(in); try { out.connect(in); producer.start(); consumer.start(); } catch (IOException e) { e.printStackTrace(); }}
运行结果如下:
缓冲区的内容为: Hello World!!!
2 源码分析
按照演示程序运行过程分析源码,主要有构造方法、connect、out写、in读等。
2.1 PipedOutputStream构造方法
/** * Creates a piped output stream connected to the specified piped * input stream. Data bytes written to this stream will then be * available as input from <code>snk</code>. * * @param snk The piped input stream to connect to. * @exception IOException if an I/O error occurs. */public PipedOutputStream(PipedInputStream snk) throws IOException { connect(snk);}/** * Creates a piped output stream that is not yet connected to a * piped input stream. It must be connected to a piped input stream, * either by the receiver or the sender, before being used. * * @see java.io.PipedInputStream#connect(java.io.PipedOutputStream) * @see java.io.PipedOutputStream#connect(java.io.PipedInputStream) */public PipedOutputStream() {}
2.2 PipedInputStream构造方法
/** * Creates a <code>PipedInputStream</code> so that it is * connected to the piped output stream * <code>src</code> and uses the specified pipe size for * the pipe's buffer. * Data bytes written to <code>src</code> will then * be available as input from this stream. * * @param src the stream to connect to. * @param pipeSize the size of the pipe's buffer. * @exception IOException if an I/O error occurs. * @exception IllegalArgumentException if {@code pipeSize <= 0}. * @since 1.6 */public PipedInputStream(PipedOutputStream src, int pipeSize) throws IOException { initPipe(pipeSize); connect(src);}public PipedInputStream(PipedOutputStream src) throws IOException { this(src, DEFAULT_PIPE_SIZE);}/** * Creates a <code>PipedInputStream</code> so that it is not yet * {@linkplain #connect(java.io.PipedOutputStream) connected} and * uses the specified pipe size for the pipe's buffer. * It must be {@linkplain java.io.PipedOutputStream#connect( * java.io.PipedInputStream) * connected} to a <code>PipedOutputStream</code> before being used. * * @param pipeSize the size of the pipe's buffer. * @exception IllegalArgumentException if {@code pipeSize <= 0}. * @since 1.6 */public PipedInputStream(int pipeSize) { initPipe(pipeSize);}public PipedInputStream() { initPipe(DEFAULT_PIPE_SIZE);}
2.3 PipedOutputStream connect方法
/** * Connects this piped output stream to a receiver. If this object * is already connected to some other piped input stream, an * <code>IOException</code> is thrown. * <p> * If <code>snk</code> is an unconnected piped input stream and * <code>src</code> is an unconnected piped output stream, they may * be connected by either the call: * <blockquote><pre> * src.connect(snk)</pre></blockquote> * or the call: * <blockquote><pre> * snk.connect(src)</pre></blockquote> * The two calls have the same effect. * * @param snk the piped input stream to connect to. * @exception IOException if an I/O error occurs. */public synchronized void connect(PipedInputStream snk) throws IOException { if (snk == null) { throw new NullPointerException(); } else if (sink != null || snk.connected) { throw new IOException("Already connected"); } sink = snk; //设置输入流 snk.in = -1; //写入缓冲区下标 snk.out = 0; //读取缓冲区下标 snk.connected = true; //设置连接状态}
2.4 PipedOutputStream write方法
/** * Writes the specified <code>byte</code> to the piped output stream. * <p> * Implements the <code>write</code> method of <code>OutputStream</code>. * * @param b the <code>byte</code> to be written. * @exception IOException if the pipe is <a href=#BROKEN> broken</a>, * {@link #connect(java.io.PipedInputStream) unconnected}, * closed, or if an I/O error occurs. */public void write(int b) throws IOException { if (sink == null) { throw new IOException("Pipe not connected"); } sink.receive(b); //直接调用输入流方法操作输入流缓冲区}/** * Receives a byte of data. This method will block if no input is * available. * @param b the byte being received * @exception IOException If the pipe is <a href="#BROKEN"> <code>broken</code></a>, * {@link #connect(java.io.PipedOutputStream) unconnected}, * closed, or if an I/O error occurs. * @since JDK1.1 */protected synchronized void receive(int b) throws IOException { checkStateForReceive(); //检查可写入状态 writeSide = Thread.currentThread(); //获取输入流线程 if (in == out) //满,即缓冲区数据已读取完 awaitSpace(); if (in < 0) { //缓冲区为空 in = 0; out = 0; } buffer[in++] = (byte)(b & 0xFF); //写入,限定为8位 if (in >= buffer.length) { // in = 0; }}
2.5 PipedInputStream read方法
/** * Reads the next byte of data from this piped input stream. The * value byte is returned as an <code>int</code> in the range * <code>0</code> to <code>255</code>. * This method blocks until input data is available, the end of the * stream is detected, or an exception is thrown. * * @return the next byte of data, or <code>-1</code> if the end of the * stream is reached. * @exception IOException if the pipe is * {@link #connect(java.io.PipedOutputStream) unconnected}, * <a href="#BROKEN"> <code>broken</code></a>, closed, * or if an I/O error occurs. */public synchronized int read() throws IOException { if (!connected) { throw new IOException("Pipe not connected"); } else if (closedByReader) { throw new IOException("Pipe closed"); } else if (writeSide != null && !writeSide.isAlive() && !closedByWriter && (in < 0)) { throw new IOException("Write end dead"); } readSide = Thread.currentThread(); //获取当前读取线程 int trials = 2; while (in < 0) { //没有可读内容 if (closedByWriter) { /* closed by writer, return EOF */ return -1; } if ((writeSide != null) && (!writeSide.isAlive()) && (--trials < 0)) { throw new IOException("Pipe broken"); } /* might be a writer waiting */ notifyAll(); //通知写入 try { wait(1000); } catch (InterruptedException ex) { throw new java.io.InterruptedIOException(); } } int ret = buffer[out++] & 0xFF; //读取字节 if (out >= buffer.length) { //超过缓冲区长度,则从头开始读,写的时候一样,所以能保证读写一样顺序 out = 0; } if (in == out) { //没有可读内容 /* now empty */ in = -1; //receive中将out置为0 } return ret;}
参考:
[1] http://www.cnblogs.com/skywang12345/p/io_04.html
[2] http://www.2cto.com/kf/201402/279143.html
[3] http://www.cnblogs.com/meng72ndsc/archive/2010/12/23/1915358.html
0 0
- Java IO:PipedOutputStream和PipedInputStream使用详解及源码分析
- 【Java-IO】PipedInputStream和PipedOutputStream
- java io系列04之 管道(PipedOutputStream和PipedInputStream)的简介,源码分析和示例
- java io系列04之 管道(PipedOutputStream和PipedInputStream)的简介,源码分析和示例
- Java IO - PipedOutputStream & PipedInputStream
- PipedInputStream,PipedOutputStream源码分析
- 使用PipedOutputStream和PipedInputStream
- Java IO流 PipedInputStream类和PipedOutputStream类
- java(5)--IO流之PipedInputStream和PipedOutputStream
- Java-IO之管道(PipedInputStream和PipedOutputStream)
- 【java基础:IO】管道流PipedInputStream和PipedOutputStream的Demostration
- Java-PipedOutputStream和PipedInputStream类
- java io 笔记三:PipedOutputStream、PipedInputStream类
- Java IO--管道流PipedOutputStream/PipedInputStream
- Java IO(八):PipedInputStream & PipedOutputStream
- java IO笔记(PipedInputStream/PipedOutputStream)
- 黑马程序员——Java基础——IO流笔记(PipedInputStream和PipedOutputStream使用示例)
- PipedInputStream和PipedOutputStream的使用例子
- Chapter 20 Linux Coding Style
- 栈的顺序存储结构
- 百万级PV高可用网站架构设计
- 深入浅出seesion和cookie
- Sublime text快捷键汇总
- Java IO:PipedOutputStream和PipedInputStream使用详解及源码分析
- php程序中实现图片的上传和下载
- 数字签名是什么?
- 队列、优先队列的学习
- IOS学习之——UIRefreshControl下拉刷新控件
- 16年4月21号:Git版本控制工具的使用
- maven打包的时候 ,将依赖包 打进同一个jar包命令 mvn assembly:assembly -DskipTests
- 连连看核心算法代码
- 对string的排序