Java IO 中的管道为运行在同一个 JVM 中的两个线程提供了通信能力。因此管道既可以是数据源也可以是目标媒介。
阅读文章的过程中如果有任何疑问,欢迎添加笔者为好友,拉您进【七日书摘】微信交流群,一起交流技术,一起打造高质量的职场技术交流圈子,抱团取暖,共同进步。
不能使用管道与不同 JVM(即不同进程) 中的线程进行通信,Java 中管道的概念不同于 Unix/Linux 系统中的管道概念。在 Unix/Linux 中,运行在不同地址空间的两个进程可以通过管道进行通信。但在 Java 中,通信的双方只能是运行在同一进程内的不同线程。
通过Java IO创建管道(Creating Pipes via Java IO)
可以通过 Java IO 中的 PipedOutputStream 和 PipedInputStream 创建管道。一个 PipedInputStream 流应该和一个 PipedOutputStream 流相关联。一个线程写入 PipedOutputStream 的数据可以被另一个线程通过相关联的 PipedInputStream 读取出来。
Java IO管道示例(Java IO Pipe Example)
下面是一个说明如何将 PipedInputStream 连接到PipedOutputStream 的简单的示例:
import java.io.IOException;
import java.io.PipedInputStream;
import java.io.PipedOutputStream;
public class PipeExample {
public static void main(String[] args) throws IOException {
final PipedOutputStream output = new PipedOutputStream();
final PipedInputStream input = new PipedInputStream(output);
Thread thread1 = new Thread(new Runnable() {
@Override
public void run() {
try {
output.write("Hello world, pipe!".getBytes());
} catch (IOException e) {
}
}
});
Thread thread2 = new Thread(new Runnable() {
@Override
public void run() {
try {
int data = input.read();
while(data != -1){
System.out.print((char) data);
data = input.read();
}
} catch (IOException e) {
}
}
});
thread1.start();
thread2.start();
}
}
//编者注:本示例忽略了流使用后需要进行关闭。请各位童鞋在处理流的过程中,务必确保关闭流,或者使用 jdk7 引入的 try-resources 代替显示地调用 close 方法的方式进行关闭流操作。
你也可以使用两个管道流共有的 connect() 方法使之相关联。PipedInputStream 和 PipedOutputStream 都拥有一个可以互相关联的 connect() 方法。
示例如下:
import java.io.IOException;
import java.io.PipedInputStream;
import java.io.PipedOutputStream;
public class PipeExample2 {
public static void main(String[] args) {
try {
PipedOutputStream output = new PipedOutputStream();
PipedInputStream input = new PipedInputStream();
// 使用 connect() 连接 output
input.connect(output);
Thread thread1 = new Thread(new Runnable() {
@Override
public void run() {
try {
output.write("Hello world, pipe!".getBytes());
output.close();
} catch (IOException e) {
e.printStackTrace();
}
}
});
Thread thread2 = new Thread(new Runnable() {
@Override
public void run() {
try {
int data = input.read();
while (data != -1) {
System.out.print((char) data);
data = input.read();
}
input.close();
} catch (IOException e) {
e.printStackTrace();
}
}
});
thread1.start();
thread2.start();
} catch (Exception e) {
// TODO:
}
}
}
管道和线程(Pipes and Threads)
同时请记住,当使用两个相关联/连接的管道流时,务必将它们分配给不同的线程。read() 方法和 write() 方法调用时会导致流阻塞,这意味着如果你尝试在同一个线程中同时进行读和写,这可能会导致线程死锁。
管道的替代方案(Pipe Alternatives)
除了管道之外,在一个 JVM 中不同线程之间的通信还有许多的方式。实际上,线程在大多数情况下会传递完整的对象信息而非原始的字节数据。但是,如果你需要在线程之间传递字节数据,Java IO 的管道是一个不错的选择。
------完------
推荐阅读:
参考资料:
https://blog.csdn.net/i_am_kop/article/details/78513802
http://ifeve.com/java-io-%e7%ae%a1%e9%81%93/