Java中管道流的使用
- 管道流包括四个类
PipedOutputStream/PipedWriter
(写入、发送者)和PipedInputStream/PipedReader
(读取、接收者) - Java管道是通过循环换种数来实现的。输入流
PipInputStream
从这个循环缓冲数组中读数据,输出流PipedOutputStream
往这个循环缓冲数组中写入数据。当这个缓冲数组已满的时候,输出流所在的线程将阻塞,当这个缓冲数组为空的时候,输入流所在的线程将阻塞 - 类
PipedInputStream
运用的是一个1024字节固定大小的循环缓冲区。 实际上,写入PipedOutputStream
的数据保存到对应的 PipedInputStream
的内部缓冲区。如果对应的 PipedInputStream
输入缓冲区已满,再次企图写入PipedOutputStream
的线程都将被阻塞,直至出现读取PipedInputStream
的操作从缓冲区删除数据 - 比起文件流、字节数组流和对象流这样使用很普遍的流,管道流有很多不同之处。首先它必须依附线程对象,当线程对象已经失效而流未关闭时会出错;其次它往往读不到-1,因此在很多场景中需要程序员自己来保证同步;第三管道流能够保证良好的互斥,这往往是很有用的一点。多加练习,管道流大有用武之地
使用管道流时,需要注意下面几点:
- 管道流仅用于多个线程之间传递信息,若在同一个线程内部,可能会造成死锁
- 管道流的输入输出是成对的,一个输出流只能对应一个输入流,使用构造函数或者
connect
函数进行连接 - 一对管道流包含一个缓冲区,其默认值为1024个字节,若要改变缓冲区大小,可以使用带有参数的构造器
- 管道的读写操作是互相阻塞的,当缓冲区为空时,读操作阻塞。当缓冲区满时,写操作阻塞
- 管道依附于线程,因此若线程借宿,则虽然管道流对象还在,仍然会报错
“read dead end”
- 管道流的读取方法与普通流不同,只有输出流正确closed时,输出流才能读到1值
字节流管道流的使用
public class MainClass {
public static void main(String[] args) throws Exception {
PipedOutputStream writer = new PipedOutputStream();
PipedInputStream reader = new PipedInputStream();
writer.connect(reader);
ThreadWriter threadWriter = new ThreadWriter(writer);
ThreadReader threadReader = new ThreadReader(reader);
threadWriter.start();
threadReader.start();
}
}
class ThreadWriter extends Thread {
private PipedOutputStream writer;
public ThreadWriter(PipedOutputStream writer) {
super();
this.writer = writer;
}
@Override
public void run() {
try {
for (int i = 0; i < 10; i++) {
writer.write(("write->" + i).getBytes());
writer.flush();
Thread.sleep(100);
}
writer.close();
} catch (Exception e1) {
e1.printStackTrace();
}
}
}
class ThreadReader extends Thread {
private PipedInputStream reader;
public ThreadReader(PipedInputStream reader) {
super();
this.reader = reader;
}
@Override
public void run() {
try {
int len = -1;
byte[] buffer = new byte[1024];
while ((len = reader.read(buffer)) != -1) {
System.out.println("ThreadReader:||||" + new String(buffer, 0, len));
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
字符管道流的使用
public class MainClass {
public static void main(String[] args) throws Exception {
PipedWriter writer = new PipedWriter();
PipedReader reader = new PipedReader();
writer.connect(reader);
ThreadWriter threadWriter = new ThreadWriter(writer);
ThreadReader threadReader = new ThreadReader(reader);
threadWriter.start();
threadReader.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 < 100; i++) {
writer.write("ThreadWriter->" + i + "\n");
writer.flush();
Thread.sleep(100);
}
writer.close();
} catch (Exception 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();
}
}
}