请大家尊重劳动成果,转载请注明出处:http://blog.csdn.net/caoshichao520326/article/details/8995583
Java多线程之间要交换信息,有时只能用管道来完成,在使用管道通信时,经常会碰到“java - IOException: Read end dead”或者“java - IOException: Write end dead”的异常,下面针对这个问题作出一个简单的分析,首先是写了一个管道通信的demo供大家参考。程序如下:
package com.csc.pipetest;
import java.io.IOException;
import java.io.PipedInputStream;
import java.io.PipedOutputStream;
/**
* 管道通信demo
*
* @author csc
*
*/
public class PipeTest {
public static void main(String[] args) {
// 创建管道输出流
PipedOutputStream pos = new PipedOutputStream();
// 创建管道输入流
PipedInputStream pis = new PipedInputStream();
try {
// 将管道输入流与输出流连接 此过程也可通过重载的构造函数来实现
pos.connect(pis);
} catch (IOException e) {
e.printStackTrace();
}
// 创建生产者线程
Producer p = new PipeTest().new Producer(pos);
// 创建消费者线程
Consumer c = new Consumer(pis);
// 启动线程
p.start();
c.start();
}
// 生产者线程(与一个管道输入流相关联)
private class Producer extends Thread {
private PipedOutputStream pos;
public Producer(PipedOutputStream pos) {
this.pos = pos;
}
public void run() {
int i = 8;
// while (true) {//加入此句将出现“java - IOException: Read end dead”异常
try {
pos.write(i);
} catch (IOException e) {
e.printStackTrace();
}
// }
}
}
// 消费者线程(与一个管道输入流相关联)
private static class Consumer extends Thread {
private PipedInputStream pis;
public Consumer(PipedInputStream pis) {
this.pis = pis;
}
public void run() {
// while(true){//加入此句将出现“java - IOException: Write end dead”异常
try {
System.out.println(pis.read());
} catch (IOException e) {
e.printStackTrace();
}
// }
}
}
}
上面的程序是可以正确运行的,①若将第46行和第52行注释掉的代码加上,将会抛出“java - IOException: Read end dead”。②若将第66行和第72行注释掉的代码加上,将会抛出“java - IOException: Write end dead”。原因都是一样的:在利用管道读写数据时,必须保证利用管道读写数据的线程都不能退出。针对上面的程序,如果是第①种情况,是因为Consumer(消费者)线程在读出管道中的数据后,线程就运行结束退出了。这时再向建立链接管道的线程Producer中写入数据时就会抛出异常。同样,如果是第②种情况就,是因为Producer(生产者)线程在写入管道中的数据后,线程就运行结束退出了。这时再由建立链接管道的线程Consumer中读出数据时就会抛出异常。
细心的读者会发现,程序的第37行和第58行在创建内部类是一个使用了“static”关键字,一个没有使用,这决定了程序的第28行和第30行在使实例化对象时的方式不同,这是创建内部类要求的否则会出现编译错误,详细分析见:http://blog.csdn.net/caoshichao520326/article/details/8961297