Java PipedInputSream/PipedOutputStream的使用及源码分析

PipedInputSream/PipedOutputStream

首先:这两个类就是为了在线程之间传输数据,通过使用这两个类来实现各个程序模块之间的松耦合通信。

一个PipedInputStream应该只一个PipedOutputStream 绑定,不然可能造成状态混乱的。

关于其内部源码的实现:

  1. 内部默认缓存数组大小1024

  2. PipedInputSream/PipedOutputStream这套机制的总体思想是阻塞的读、写缓存数组,这个缓存数组是PipedInputStream的成员变量。若数组为空则Input阻塞等到缓存数组有数据写入,若数组满了则Output阻塞等到数组有空余。

  3. PipedOutputStream的write()内部其实是调用的PipedInputStream的receive()方法,且该方法是synchronized 修饰的。receive方法内部当缓存数组写满是,就会调用wait(1000)阻塞住调用PipedOutputStream的write线程,直到缓存数组可写。
    而当调用PipedInputStream的read()方法时,如果缓存数组为空,read()方法内部也会调用wait(1000)阻塞当前的read线程,直到缓存数组中有数据写入

举个栗子:

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

class Producer extends Thread {
    PipedOutputStream outputStream;

    public Producer(PipedInputStream inputStream) throws IOException {
        this.outputStream = new PipedOutputStream(inputStream);
    }

    private void produce() throws IOException {
        byte[] data1 = "Hello Consumer.我是生产者".getBytes();
        System.out.println("data1 len=" + data1.length);
        System.out.println("data2 len=10240");
        byte[] data2 = new byte[1024 * 10];
        for (int i = 0; i < 1024 * 10; i++) {
            data2[i] = 3;
        }

        this.outputStream.write(data1);
        System.out.println("producer wrote data1");
        this.outputStream.write(data2);
        System.out.println("producer wrote data2");

        outputStream.close();
        /**
        这里要记得关闭输出流。这个close被override了,这个函数内部是调用了PipedInputStream中的receivedLast函数,其会设置PipedInputStream的成员变量closedByWriter 为true,从而下次read的时候返回-1
        如果没有关闭的话,producer线程直接退出,会导致consumer在read的时候抛错:java.io.IOException: Write end dead。

        receivedLast源码,JDK1.7
        synchronized void receivedLast() {
            closedByWriter = true;
            notifyAll();//通知还在阻塞等待的read线程或write线程。
         }

        **/
    }

    @Override
    public void run() {
        try {
            produce();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

}

class Consumer extends Thread {

    PipedInputStream inputStream = new PipedInputStream();


    private void consume() throws IOException {
        byte[] buf = new byte[2048];
        int offset = this.inputStream.read(buf);
        System.out.println("consumer read data1:" + new String(Arrays.copyOfRange(buf, 0, 15 + 5 * 3)));//不指定编码的话,将采用系统默认编码。本机默认编码是UTF-8。因此因此英文占1字节,中文占3字节

        int data2Len = offset - 30;
        while (offset != -1) {
            offset = this.inputStream.read(buf);
            if (offset != -1) data2Len += offset;
        }
        System.out.println("consumer read data2 len:" + data2Len);

        inputStream.close();
    }

    public PipedInputStream getInputStream() {
        return inputStream;
    }

    @Override
    public void run() {
        try {
            consume();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

public class PipedStream {

    public static void main(String[] args) throws IOException {
        String defaultCharsetName = Charset.defaultCharset().displayName();
        System.out.println("defaultCharsetName:" + defaultCharsetName);//获取默认编码字符
        Consumer consumer = new Consumer();
        Producer producer = new Producer(consumer.getInputStream());
        consumer.start();
        producer.start();
    }
}

参考:http://www.cnblogs.com/skywang12345/p/io_04.html

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章