java中PipedInputStream和PipedOutputStream分别是管道输入流和管道输出流,它的作用是让多线程可以通过管道进行线程间的通讯,在使用管道通信时,必须将PipedInputStream和PipedOutputStream配套使用。大致的流程是:当在线程A中向PipedOutputStream中写入数据,会自动发送到与PipedOutputStream对应的PipedInputStream中,进而存储在PipedInputStream的缓冲区中,此时线程B通过读取PipedInputStream中的数据,实现线程的通信。

PipedInputStream类的主要函数有:

public PipedInputStream(PipedOutputStream src)
public PipedInputStream(PipedOutputStream src, int pipeSize)
public PipedInputStream()
public PipedInputStream(int pipeSize)
public void connect(PipedOutputStream src)
protected synchronized void receive(int b)
synchronized void receive(byte b[], int off, int len)
public synchronized int read()
public synchronized int read(byte b[], int off, int len)
public synchronized int available()

PipedOutputStream类的主要函数有:

public PipedOutputStream(PipedInputStream snk)
public PipedOutputStream()
public synchronized void connect(PipedInputStream snk)
public void write(int b)
public void write(byte b[], int off, int len)

基于PipedInputStream和PipedOutputStream线程通信示例:

Send类:

public class Send extends Thread {

private PipedOutputStream outputStream=new PipedOutputStream();
    public PipedOutputStream getOutputStream()
    {
        return outputStream;
    }
    @Override
    public void run()
    {
        writeMessage();
    }

    public void writeMessage()
    {
        String string="hello pipedstream";
        try {
            outputStream.write(string.getBytes());
            outputStream.close();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
}

Receiver类:

public class Receiver extends Thread{

    private PipedInputStream inputStream=new PipedInputStream();
    public PipedInputStream getInputStream()
    {
        return inputStream;
    }

    @Override
    public void run()
    {
        readMessage();
    }

    public void readMessage()
    {
        byte[] buf=new byte[2048];
        int len;
        try {
            len = inputStream.read(buf);
            System.out.println(new String(buf,0,len));
            inputStream.close();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
}

Main函数:

public class Hello {

    public static void main(String [] args)
   {
        Send s1=new Send();
        Receiver r1=new Receiver();
        PipedInputStream inputStream=r1.getInputStream();
        PipedOutputStream outputStream=s1.getOutputStream();
      try {
         inputStream.connect(outputStream);
        s1.start();
        r1.start();
        } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
        }

   }
}
运行结果:
hello pipedstream
结果分析:
(1)inputStream.connect(outputStream);将管道输入流和输出流关联起来,代码换成outputStream.connect(inputStream)是同样的效果
(2)当调用PipedOutputStream的write()方法时,其实是调用的PipedInputStream的receiver()方法。

基于JDK8的PipedOutputStream的源码:

public class PipedOutputStream extends OutputStream {

   (but it may be a
       long time until the next GC). */
    private PipedInputStream sink;

    //构造函数,连接输出流
    public PipedOutputStream(PipedInputStream snk)  throws IOException {
        connect(snk);
    }

    //构造函数,并没有连接管道输入流,在使用之前必须进行连接
    public PipedOutputStream() {
    }

    //管道输出流和输入流进行连接,如果已经连接会抛出错误
    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;
    }

    //向输入流写数据
    public void write(int b)  throws IOException {
        if (sink == null) {
            throw new IOException("Pipe not connected");
        }
        sink.receive(b);
    }

    //想输入流写b,起始为off,长度为len
    public void write(byte b[], int off, int len) throws IOException {
        if (sink == null) {
            throw new IOException("Pipe not connected");
        } else if (b == null) {
            throw new NullPointerException();
        } else if ((off < 0) || (off > b.length) || (len < 0) ||
                ((off + len) > b.length) || ((off + len) < 0)) {
                    throw new IndexOutOfBoundsException();
        } else if (len == 0) {
            return;
        }
        sink.receive(b, off, len);
    }

    //刷新,强制任意一个输出流都被写出
    public synchronized void flush() throws IOException {
        if (sink != null) {
            synchronized (sink) {
                sink.notifyAll();
            }
        }
    }
    //关闭输出流,释放资源
    public void close()  throws IOException {
        if (sink != null) {
            sink.receivedLast();
        }
    }
}

基于JDK8的PipedInputStream的源码:

public class PipedInputStream extends InputStream {
    boolean closedByWriter = false;
    volatile boolean closedByReader = false;
    boolean connected = false;
    Thread readSide;//读线程
    Thread writeSide;//写线程
    private static final int DEFAULT_PIPE_SIZE = 1024;//默认管道大小
    protected static final int PIPE_SIZE = DEFAULT_PIPE_SIZE;

    //字节数组,循环数组,放置数据
    protected byte buffer[];

    //写的标志位为-1
    protected int in = -1;

    //读的标志位为0,当in==out表示为空,
    protected int out = 0;

    //构造函数,连接输出流
    public PipedInputStream(PipedOutputStream src) throws IOException {
        this(src, DEFAULT_PIPE_SIZE);
    }

    //构造函数,连接输出流,并设置管道大小
    public PipedInputStream(PipedOutputStream src, int pipeSize)throws IOException {
        initPipe(pipeSize);
        connect(src);
    }

    //构造函数,还没有连接输出流
    public PipedInputStream() {
        initPipe(DEFAULT_PIPE_SIZE);
    }

    //设置管道大小
    public PipedInputStream(int pipeSize) {
        initPipe(pipeSize);
    }

    private void initPipe(int pipeSize) {
        if (pipeSize <= 0) {
            throw new IllegalArgumentException("Pipe Size <= 0");
        }
        buffer = new byte[pipeSize];
    }

    //连接输出流
    public void connect(PipedOutputStream src) throws IOException {
        src.connect(this);
    }

    //读取数据
    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);
        if (in >= buffer.length) {
            in = 0;
        }
    }

    synchronized void receive(byte b[], int off, int len)  throws IOException {
        checkStateForReceive();
        writeSide = Thread.currentThread();
        int bytesToTransfer = len;
        while (bytesToTransfer > 0) {
            if (in == out)
                awaitSpace();
            int nextTransferAmount = 0;
            if (out < in) {
                nextTransferAmount = buffer.length - in;
            } else if (in < out) {
                if (in == -1) {
                    in = out = 0;
                    nextTransferAmount = buffer.length - in;
                } else {
                    nextTransferAmount = out - in;
                }
           }
        if (nextTransferAmount > bytesToTransfer)
                nextTransferAmount = bytesToTransfer;
            assert(nextTransferAmount > 0);
        System.arraycopy(b, off, buffer, in, nextTransferAmount);
        bytesToTransfer -= nextTransferAmount;
        off += nextTransferAmount;
        in += nextTransferAmount;
            if (in >= buffer.length) {
                in = 0;
            }
        }
    }

    private void checkStateForReceive() throws IOException {
        if (!connected) {
            throw new IOException("Pipe not connected");
        } else if (closedByWriter || closedByReader) {
            throw new IOException("Pipe closed");
        } else if (readSide != null && !readSide.isAlive()) {
            throw new IOException("Read end dead");
        }
    }

    private void awaitSpace() throws IOException {
        while (in == out) {
            checkStateForReceive();

            /* full: kick any waiting readers */
            notifyAll();
            try {
                wait(1000);
            } catch (InterruptedException ex) {
                throw new java.io.InterruptedIOException();
            }
        }
    }
    synchronized void receivedLast() {
        closedByWriter = true;
        notifyAll();
    }
    //从输入流中读取数据
    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;
    }
    //从输入流中读取数据到b。其实为off,大小为len
    public synchronized int read(byte b[], int off, int len)  throws IOException {
        if (b == null) {
            throw new NullPointerException();
        } else if (off < 0 || len < 0 || len > b.length - off) {
            throw new IndexOutOfBoundsException();
        } else if (len == 0) {
            return 0;
        }

        /* possibly wait on the first character */
        int c = read();
        if (c < 0) {
            return -1;
        }
        b[off] = (byte) c;
        int rlen = 1;
        while ((in >= 0) && (len > 1)) {

            int available;

            if (in > out) {
                available = Math.min((buffer.length - out), (in - out));
            } else {
                available = buffer.length - out;
            }

            // A byte is read beforehand outside the loop
            if (available > (len - 1)) {
                available = len - 1;
            }
            System.arraycopy(buffer, out, b, off + rlen, available);
            out += available;
            rlen += available;
            len -= available;

            if (out >= buffer.length) {
                out = 0;
            }
            if (in == out) {
                /* now empty */
                in = -1;
            }
        }
        return rlen;
    }
    //判断是否还有数据
    public synchronized int available() throws IOException {
        if(in < 0)
            return 0;
        else if(in == out)
            return buffer.length;
        else if (in > out)
            return in - out;
        else
            return in + buffer.length - out;
    }
    //关闭资源
    public void close()  throws IOException {
        closedByReader = true;
        synchronized (this) {
            in = -1;
        }
    }
}

Java-IO之管道(PipedInputStream和PipedOutputStream)的更多相关文章

  1. 系统学习 Java IO (六)----管道流 PipedInputStream/PipedOutputStream

    目录:系统学习 Java IO---- 目录,概览 PipedInputStream 类使得可以作为字节流读取管道的内容. 管道是同一 JVM 内的线程之间的通信通道. 使用两个已连接的管道流时,要为 ...

  2. JAVA IO之管道流总结大全(转)

    要在文本框中显示控制台输出,我们必须用某种方法“截取”控制台流.换句话说,我们要有一种高效地读取写入到System.out和 System.err 所有内容的方法.如果你熟悉Java的管道流Piped ...

  3. Java I/O流-PipedInputStream、PipedOutputStream

    一.整体代码图 PipedStreamDemo.java import java.io.*; class PipedStreamDemo { public static void main(Strin ...

  4. java io之管道流

    一.java.io中存在一中流叫管道流,类似管道的功能.PipedOutputStream和PipedInputStream分别是管道输出流和管道输入流.这个两个流必须同时使用. 二.作用:进行两个线 ...

  5. java io系列04之 管道(PipedOutputStream和PipedInputStream)的简介,源码分析和示例

    本章,我们对java 管道进行学习. 转载请注明出处:http://www.cnblogs.com/skywang12345/p/io_04.html java 管道介绍 在java中,PipedOu ...

  6. Java IO: PipedInputStream

    原文链接 作者: Jakob Jenkov 译者: 李璟(jlee381344197@gmail.com) PipedInputStream可以从管道中读取字节流数据,代码如下: 01 InputSt ...

  7. Java IO: 管道

    原文链接 作者: Jakob Jenkov  译者: 李璟(jlee381344197@gmail.com) Java IO中的管道为运行在同一个JVM中的两个线程提供了通信的能力.所以管道也可以作为 ...

  8. Java IO学习--(三)通道

    Java IO中的管道为运行在同一个JVM中的两个线程提供了通信的能力.所以管道也可以作为数据源以及目标媒介. 你不能利用管道与不同的JVM中的线程通信(不同的进程).在概念上,Java的管道不同于U ...

  9. Java基础17:Java IO流总结

    更多内容请关注微信公众号[Java技术江湖] 这是一位阿里 Java 工程师的技术小站,作者黄小斜,专注 Java 相关技术:SSM.SpringBoot.MySQL.分布式.中间件.集群.Linux ...

  10. 系统学习 Java IO ---- 目录,概览

    Java IO 类的系统教程,原创.主要参考自英文教程 Java IO Tutorial 和 Java Doc. http://tutorials.jenkov.com/java-io/index.h ...

随机推荐

  1. rsync 系统用户/虚拟用户 备份web服务器数据及无交互定时推送备份

    一.服务环境 (1),WEBserver(192.168.10.130) : BACKserver(192.168.10.129) (2),BACKserver服务器部署,安装所需软件,并启动 (3) ...

  2. Cisco 的基本配置实例之四----vlan的规划及配置(核心交换机)

    4.vlan的规划及配置 在本节中我们讲解vlan的规划及具体的配置命令.在此例中我们用的是vtp(VLAN Trunking Protocol)server的模式,在这种模式中我们需要配置核心交换机 ...

  3. iframe嵌套页面 音频在微信公众号环境无法播放

    在微信公众号中 没有iframe的时候window.WeixinJSBridge为对象,有iframe时为undefined 要使用 window.parent.WeixinJSBridge得到 if ...

  4. idea Library XXXXXXXX has broken classes paths

    点fix 然后全部 全部按- 删掉 一开始以为会影响很大 后来发现他地址错了都导不进 要是真要用到的时候也没用 还是要maven单独导进来

  5. TypeScript知识点

    TypeScript介绍 TypeScript为JavaScript的超集(ECMAScript6), 这个语言添加了基于类的面向对象编程.TypeScript作为JavaScript很大的一个语法糖 ...

  6. Socket网络编程详解

    一,socket的起源 socket一词的起源 在组网领域的首次使用是在1970年2月12日发布的文献IETF RFC33中发现的, 撰写者为Stephen Carr.Steve Crocker和Vi ...

  7. Oracle中建库时报Exception in thread main

    Linux操作系统上安装oracle 10g,在启动dbca的时候报 Exception in thread "main" 错误,详细内容如下: [oracle@centos ~] ...

  8. truncated、delete和drop的异同点

    相同点 truncate和不带where子句的delete, 以及drop都会删除表内的数据. 不同点: 1.truncate和 delete只删除数据不删除表的结构(定义) drop语句将删除表的结 ...

  9. 条件语句,while循环语句:完整的温度转换程序

    while True: a = int(input('摄氏温度换为华氏温度请按 1\n华氏温度转为摄氏温度请按 2\n退出请按 3\n')) if a==1: c = float(input('请输入 ...

  10. PHP 包含

    PHP 包含文件 PHP include 和 require 语句 在 PHP 中,您可以在服务器执行 PHP 文件之前在该文件中插入一个文件的内容. include 和 require 语句用于在执 ...