本教程操作环境:windows7系统、java10版,DELL G3电脑。
1.创建和连接管道两端的两种方法
(1)创建管道输入和输出流并连接它们。它使用connect方法连接两个流。PipedInputStream pis = new PipedInputStream();
PipedOutputStream pos = new PipedOutputStream();
pis.connect(pos); /* Connect the two ends */
(2)创建管道输入和输出流并连接它们。它通过将输入管道流传递到输出流构造器来连接两个流。PipedInputStream pis = new PipedInputStream();
PipedOutputStream pos = new PipedOutputStream(pis);
2.写入报错分析
在线程Sender中向管道流中写入一个字符串,写入后关闭该管道流;在线程Reciever中读取该字符串。import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.PipedInputStream;
import java.io.PipedOutputStream;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
public class PipedStreamExam1 {
public static void main(String[] args) {
ExecutorService executorService = Executors.newCachedThreadPool();
try {
//创建管道流
PipedOutputStream pos = new PipedOutputStream();
PipedInputStream pis = new PipedInputStream(pos);
//创建线程对象
Sender sender = new Sender(pos);
Reciever reciever = new Reciever(pis);
//运行子线程
executorService.execute(sender);
executorService.execute(reciever);
} catch (IOException e) {
e.printStackTrace();
}
//等待子线程结束
executorService.shutdown();
try {
executorService.awaitTermination(1, TimeUnit.DAYS);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
static class Sender extends Thread {
private PipedOutputStream pos;
public Sender(PipedOutputStream pos) {
super();
this.pos = pos;
}
@Override
public void run() {
try {
String s = "This is a good day. 今天是个好天气。";
System.out.println("Sender:" + s);
byte[] buf = s.getBytes();
pos.write(buf, 0, buf.length);
pos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
static class Reciever extends Thread {
private PipedInputStream pis;
public Reciever(PipedInputStream pis) {
super();
this.pis = pis;
}
@Override
public void run() {
try {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
byte[] buf = new byte[1024];
int len = 0;
while ((len = pis.read(buf)) != -1) {
baos.write(buf, 0, len);
}
byte[] result = baos.toByteArray();
String s = new String(result, 0, result.length);
System.out.println("Reciever:" + s);
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
注意,若管道流没有关闭,则使用这种方法读取管道中的信息会报错:while ((len = pis.read(buf)) != -1) {
baos.write(buf, 0, len);
}
错误代码为java.io.IOException: Write end dead;发生这个错误的原因在于,由于管道未关闭,所以read语句不会读到-1,因此PipedInputStream会持续从管道中读取数据,但是因为Sender线程已经结束,所以会抛出“Write end dead”异常。
以上就是java管道流写入报错的原因分析,这是因为线程结束而管道流持续作用的结果。下次大家在使用的时候,需要注意多线的运行状态,避免此类报错的产生。