Java管道流

1、管道流是用来在多个线程之间进行信息传递的Java流,被号称是难使用的流,被使用的频率比较低。它提供了多线程间信息传输的一种有效手段
2、管道流包括四个类 PipedOutputStream/PipedWriter 和 PipedInputStream/PipedReader
3、其中 PipedOutputStream/PipedWriter 是写入者/生产者/发送者;PipedInputStream/PipedReader 是读取者/消费者/接收者
4、这里我们只分析字节管道流,字符管道流原理跟字节管道流一样,只不过底层一个是 byte 数组存储 一个是 char 数组存储的
5、java的管道输入与输出实际上使用的是一个循环缓冲数来实现的。输入流PipedInputStream从这个循环缓冲数组中读数据,输出流PipedOutputStream往这个循环缓冲数组中写入数据。当这个缓冲数组已满的时候,输出流PipedOutputStream所在的线程将阻塞;当这个缓冲数组为空的时候,输入流PipedInputStream所在的线程将阻塞
在使用管道流之前,需要注意以下要点:
(1)管道流仅用于多个线程之间传递信息,若用在同一个线程中可能会造成死锁
(2)管道流的输入输出是成对的,一个输出流只能对应一个输入流,使用构造函数或者 connect 函数进行连接
(3)一对管道流包含一个缓冲区,其默认值为1024个字节,若要改变缓冲区大小,可 以使用带有参数的构造器
(4)管道的读写操作是互相阻塞的,当缓冲区为空时,读操作阻塞。当缓冲区满时,写操作阻塞
(5)管道依附于线程,因此若线程结束,则虽然管道流对象还在,仍然会报错“read dead end”
(6)管道流的读取方法与普通流不同,只有输出流正确 close 时,输出流才能读到1值。

/**
 * 管道流
 * PipedOutputStream/PipedWriter和PipedInputStream/PipedReader
 * 
 * @author sxj
 *
 */
public class PipedStreamDemo {
	public static void main(String[] args) throws IOException {
		PipedWriter writer=new  PipedWriter();
		PipedReader reader=new PipedReader();
		//连接两个线程的管道流
		writer.connect(reader);
		
		ThreadWriter one=new ThreadWriter(writer);
		ThreadReader two=new ThreadReader(reader);
		
		one.start();
		two.start();
	}
}



class ThreadWriter extends Thread{
	//声明管道流
	private PipedWriter writer;
	//构造器
	public ThreadWriter(PipedWriter writer) {
		super();
		this.writer = writer;
	}
	@Override
	public void run() {
		try {
			for (int i = 0; i < 10; i++) {
				writer.write("这是ThreadWriter! count:"+i+"\r\n");
				writer.flush();
			}
			writer.close();
		} catch (IOException e1) {
			e1.printStackTrace();
		}
	}
}

class ThreadReader extends Thread{
	//声明管道流 发送着和接收者
	private PipedReader reader;
	//构造器
	public ThreadReader(PipedReader reader) {
		super();
		this.reader = reader;
	}
	@Override
	public void run() {
		try {
			String str="";
			BufferedReader bReader=new BufferedReader(reader);
			while ((str=bReader.readLine())!=null) {
				System.out.println("ThreadReader:"+str);
			}
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
}

示例代码执行结果:
Java管道流_第1张图片
1、类PipedInputStream运用的是一个1024字节固定大小的循环缓冲区。 实际上,写入PipedOutputStream的数据保存到对应的 PipedInputStream的内部缓冲区。如果对应的 PipedInputStream输入缓冲区已满,再次企图写入PipedOutputStream的线程都将被阻塞,直至出现读取PipedInputStream的操作从缓冲区删除数据
2、比起文件流、字节数组流和对象流这样使用很普遍的流,管道流有很多不同之处。首先它必须依附线程对象,当线程对象已经失效而流未关闭时会出错;其次它往往读不到-1,因此在很多场景中需要程序员自己来保证同步;第三管道流能够保证良好的互斥,这往往是很有用的一点。多加练习,管道流大有用武之地

你可能感兴趣的:(Java管道流)