- 在Java语言中提供了各种各样的输人/输出流Stream,使我们能够很方便地对数据进行操作,其中管道流(pipeStream)是一种特殊的流,用于在不同线程间直接传送数据。一个线程发送数据到输出管道,另一个线程从输人管道中读数据。通过使用管道,实现不同线程间的通信,而无须借助于类似临时文件之类的东西。在Java的JDK中提供了4个类来使线程间可以进行通信:
字节流: PipedInputStream和PipedOutputStream
字符流: PipedReader和 PipedWriter
PS: 无论使用哪一对流, 都要使俩个流(输入与输出)建立连接, 这样才可以将数据进行输出与输入
字节流
- PipedInputStream和PipedOutputStream
代码演示
public class WriteStreamDate {
public void writeDate(PipedOutputStream pipedOutputStream) {
System.out.println(Thread.currentThread().getName() + " 开始向管道中写东西");
try {
for (char ch = 'a'; ch <= 'z'; ch++) {
String date = ch + " ";
pipedOutputStream.write(date.getBytes());
}
pipedOutputStream.flush();
pipedOutputStream.close();
System.out.println(Thread.currentThread().getName() + " 写数据完毕");
} catch (IOException e) {
e.printStackTrace();
}
}
}
public class ReadStreamDate {
public void readDate(PipedInputStream pipedInputStream) {
System.out.println(Thread.currentThread().getName() + " 开始从管道中读数据");
byte[] buffer = new byte[20];
int len = -1;
try {
while ((len = (pipedInputStream.read(buffer))) != -1) {
String date = new String(buffer, 0, len);
System.out.print(date);
}
System.out.println();
pipedInputStream.close();
System.out.println(Thread.currentThread().getName() + " 读完毕");
} catch (IOException e) {
e.printStackTrace();
}
}
}
public class Run {
public static void main(String[] args) throws IOException, InterruptedException {
PipedInputStream pipedInputStream = new PipedInputStream();
PipedOutputStream pipedOutputStream = new PipedOutputStream();
pipedInputStream.connect(pipedOutputStream);
WriteStreamDate writeStreamDate = new WriteStreamDate();
ReadStreamDate readStreamDate = new ReadStreamDate();
Thread a = new Thread("A") {
@Override
public void run() {
writeStreamDate.writeDate(pipedOutputStream);
}
};
Thread b = new Thread("B") {
@Override
public void run() {
readStreamDate.readDate(pipedInputStream);
}
};
b.start();
Thread.sleep(100);
a.start();
Thread.sleep(100);
}
}
- 运行结果
- 上述代码首先是读取线程启动,由于当时没有数据被写人,所以线程阻塞在len = (pipedInputStream.read(buffer);代码中,直到有数据被写入并且执行colse方法,才继续向下运行。当然如果是写线程先启动就没这个问题.
字符流
代码演示
public class WriteDate {
public void write(PipedWriter pipedWriter) {
System.out.println(Thread.currentThread().getName() + " 开始写数据");
StringBuilder date = new StringBuilder();
try {
for (char ch = 'a'; ch <= 'g'; ch++) {
date.append(ch);
pipedWriter.write(date.toString() + " ");
}
pipedWriter.flush();
pipedWriter.close();
System.out.println(Thread.currentThread().getName() + " 写数据完毕");
} catch (IOException e) {
e.printStackTrace();
}
}
}
public class ReadDate {
public void read(PipedReader pipedReader) {
System.out.println(Thread.currentThread().getName() + " 开始读数据");
char[] buffer = new char[20];
int len = -1;
try {
while ((len = pipedReader.read(buffer)) != -1) {
String date = new String(buffer, 0, len);
System.out.println(date);
}
pipedReader.close();
System.out.println(Thread.currentThread().getName() + " 读数据完毕");
} catch (IOException e) {
e.printStackTrace();
}
}
}
public class Run2 {
public static void main(String[] args) throws IOException, InterruptedException {
PipedReader pipedReader = new PipedReader();
PipedWriter pipedWriter = new PipedWriter();
pipedReader.connect(pipedWriter);
ReadDate readDate = new ReadDate();
WriteDate writeDate = new WriteDate();
Thread a = new Thread("A") {
@Override
public void run() {
writeDate.write(pipedWriter);
}
};
Thread b = new Thread("B") {
@Override
public void run() {
readDate.read(pipedReader);
}
};
a.start();
Thread.sleep(100);
b.start();
Thread.sleep(100);
}
}
- 执行结果
- 这个代码如果是读线程提前, 问题和字节流是一样的, 依旧会阻塞在len = (pipedInputStream.read(buffer)