Java线程间通信--管道

本文详细介绍了Java中的管道流PipeStream,包括PipedInputStream和PipedOutputStream的工作原理。通过实例展示了如何使用管道流在两个线程间直接传输数据,解释了pis.read方法的阻塞特性及数据传输过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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;
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值