通过输入/输出在线程间进行通信通常很有用。线程库以“管道”(pipes)的形式对线程间
的输入/输出提供了支持。它们在 Java输入/输出库中的对应物就是 PipedWriter类(允
许线程向管道写)和PipedReader 类(允许不同线程从同一个管道中读取)。这个模型
可以看成是生产者-消费者问题的变体,这里的管道就是一个封装好的解决方案。
下面是一个简单例子,两个线程使用一个管道进行通信:
//: c13:PipedIO.java
// Using pipes for inter-thread I/O
import java.io.*;
import java.util.*;
class Sender extends Thread {
private Random rand = new Random();
private PipedWriter out = new PipedWriter();
public PipedWriter getPipedWriter() { return out; }
public void run() {
while(true){
for(charc = 'A'; c <= 'z'; c++) {
try{
out.write(c);
sleep(rand.nextInt(500));
} catch(Exceptione) {
throw newRuntimeException(e);
}
}
}
}
}
class Receiver extends Thread {
private PipedReader in;
public Receiver(Sender sender) throwsIOException
{
in = newPipedReader(sender.getPipedWriter());
}
public void run() {
try{
while(true){
// Blocks until characters are there:
System.out.println("Read:" +
(char)in.read());
}
} catch(IOExceptione) {
throw newRuntimeException(e);
}
}
}
public class PipedIO {
public static void main(String[] args) throws
Exception {
Sender sender = new Sender();
Receiver receiver = new Receiver(sender);
sender.start();
receiver.start();
new Timeout(4000, "Terminated");
}
} ///:~
Sender和Receiver代表了两个线程,它们执行某些任务并且需要互相通信。Sender创
建了一个PipedWriter,它是一个单独的对象,但是对于Receiver,PipedReader的
建立必须在构造器中与一个PipedWriter相关联。Sender把数据放进Writer然后休眠一
段随机的时间。然而,Receiver没有调用sleep( )和wait( )。但当它调用read( )
时,如果没有数据,它将自动阻塞。这样你不用使用wait( )循环,就得到了生产者-消
费者的效果。
注意到sender和receiver是在main( )中启动的,即对象构造完毕以后。如果你启动了
一个没有构造完毕的对象,在不同的平台上管道可能会产生不一致的行为。