Java线程间通信--管道

Java提供了多种输入输出流用于对数据进行操作,其中管道流pipeStream是一种特殊的流,用于在不同线程间直接传送数据。

pis.read的时候,如果管道内没有数据,会阻塞。

public class PipeStreamMain {
    public static void main(String[] args) throws IOException {
        PipedInputStream pis=new PipedInputStream();
        PipedOutputStream pos=new PipedOutputStream();

        pos.connect(pis);

        TaskReader tr=new TaskReader(pis);
        TaskWriter tw=new TaskWriter(pos);

        tr.start();
        tw.start();
    }
    static class TaskWriter extends Thread{
        private final PipedOutputStream pos;

        TaskWriter(PipedOutputStream pos){
            this.pos=pos;
        }

        @Override
        public void run() {
            System.out.println("writer开始写");
            try {
                for (int i = 0; i < 10; i++) {
                    pos.write(i);

                }
                System.out.println("写完了");
                pos.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
    static class TaskReader extends Thread{
        private final PipedInputStream pis;

        TaskReader(PipedInputStream pis){
            this.pis=pis;
        }

        @Override
        public void run() {
            System.out.println("reader ");
            byte[] bytes=new byte[5];
            try {
                int len=pis.read(bytes);
                while (len!=-1){
                    System.out.println(bytes[0]+" "+bytes[1]+" "+bytes[2]+" ");
                    len=pis.read(bytes);
                }
                pis.close();

            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

pos的write方法,会调用pis的receive方法
在这里插入图片描述

public void write(int b)  throws IOException {
        if (sink == null) {
            throw new IOException("Pipe not connected");
        }
        sink.receive(b);
    }
writeSide = Thread.currentThread();

pos的close方法,调用pis的receivedLast方法

public void close()  throws IOException {
        if (sink != null) {
            sink.receivedLast();
        }
    }

pis的read方法:
首先会尝试读取一个字节,没读取到则阻塞并每隔1秒尝试读取一次,读取到了,再判断还有没有内容,如果有则读到buf中,直到没有可读内容或者buf读满了,则返回buf给用户。

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;
    }
每次从buffer中读取一个字节,如果in==out,说明读取完了。
如果in<0,说明没有可读内容,会阻塞1秒(不断重复)。

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;
    }

猜你喜欢

转载自blog.csdn.net/ljz2016/article/details/83992124