IO--PipedInputSteamAndPipedOutputStream

原创 2015年07月09日 20:32:25

PipedInputStream和PipedOutputStream在两个线程之间建立通信的管道

比如线程A持有PipedOutputStream os,线程B持有PipedInputStream is,可以用os绑定is也可以用is绑定os。然后os写入数据,is读取数据。

import java.io.IOException;
import java.io.PipedInputStream;
import java.io.PipedOutputStream;

/**
 * Created by marsares on 15/7/9.
 */
public class Receiver extends Thread{
    private PipedInputStream in=new PipedInputStream();
    public PipedInputStream getPipedInputStream(){
        return in;
    }
    public Receiver(){}
    public Receiver(Sender s)throws IOException{
        in=new PipedInputStream(s.getPipedOutputStream());
    }
    public void run(){
        try{
            int data;
            while((data=in.read())!=-1){
                System.out.println(data);
            }
            in.close();
        }catch(IOException e){
            e.printStackTrace();
        }
    }
    public static void main(String[]args)throws IOException{
        Receiver r=new Receiver();
        Sender s=new Sender(r);
        s.start();
        r.start();
    }
}
class Sender extends Thread{
    private PipedOutputStream out;
    public PipedOutputStream getPipedOutputStream(){
        return out;
    }
    public Sender(){}
    public Sender(Receiver r)throws IOException{
        out=new PipedOutputStream(r.getPipedInputStream());
    }
    public void run(){
        try{
            for(int i=0;i<100;i++){
                out.write(i);
                //yield();
            }
            out.close();
        }catch (IOException e){
            e.printStackTrace();
        }
    }
}
从PipedOutputStream和PipedInputStream源码中可以看出这两者的绑定是对称的,只要有一个在初始化的时候绑定另一个就行了。

PipedInputStream

public PipedInputStream(PipedOutputStream src, int pipeSize)
            throws IOException {
         initPipe(pipeSize);
         connect(src);
    }
PipedOutputStream

public PipedOutputStream(PipedInputStream snk)  throws IOException {
        connect(snk);
    }
PipedOutputStream的write方法调用的PipedInputStream的receive方法,管道流本质上就是在PipedInputStream中的byte[]buffer中读和写。
public void write(int b)  throws IOException {
        if (sink == null) {
            throw new IOException("Pipe not connected");
        }
        sink.receive(b);
    }
但是这就产生一个疑问,如果只是在PipedInputStream中的buffer进行读和写,为什么需要PipedOutputStream呢?

其实管道流还有个重要的特点就是在两个线程之间建立通信通道,如果一个线程关闭了管道能够及时通知另一个线程不再等待。

PipedOutputStream关闭管道

public void close()  throws IOException {
        if (sink != null) {
            sink.receivedLast();
        }
    }
如果buffer中的数据读完并且管道关闭那么PipedInputStream跳出read。如果buffer中数据读完但是管道没有关闭,PipedInputStream将进入阻塞状态等待写进程写入数据。
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;
        }

        return ret;
    }
如果不使用PipedOutputStream就需要用户自己设定closedByWriter和closedByReader参数,造成了紧耦耦合。





相关文章推荐

java socket.io 0.8.3

  • 2017年11月17日 16:10
  • 578KB
  • 下载

commons-io-2.4.jar

  • 2017年11月09日 15:44
  • 166KB
  • 下载

Python异步非阻塞IO多路复用Select/Poll/Epoll使用

来源:http://www.haiyun.me/archives/1056.html 有许多封装好的异步非阻塞IO多路复用框架,底层在linux基于最新的epoll实现,为了更好的使用,了解其底层原...

1734-Point-IO配置手册

  • 2017年10月24日 14:58
  • 443KB
  • 下载

聊天室入门实战(node,socket.io实现)--第二章(美化,图片发送,登录提示,认证)

聊天室入门实战 node.js express socket.io jquery bootstrap 实战聊天室,实现登录检查,群聊,单聊,欢迎,下线通知等功能...

commons-io.rar

  • 2017年10月26日 17:43
  • 516KB
  • 下载

Growing IO SDK PHP版

  • 2017年10月24日 10:32
  • 2KB
  • 下载

【stm32f407】IO引脚复用和映射

一.  什么叫管脚复用 STM32F4有很多的内置外设,这些外设的外部引脚都是与GPIO复用的。也就是说,一个GPIO如果可以复用为内置外设的功能引脚,那么当这个GPIO作为内置外设使用的时候,就叫做...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:IO--PipedInputSteamAndPipedOutputStream
举报原因:
原因补充:

(最多只允许输入30个字)