当需要在两个线程中读写数据的时候,由于线程的并发执行,读写的同步问题可能会发生困难,这时候可以使用管道,管道事实上是一个队列。
管道是由系统维护的一个缓冲区,当然程序员也可以自己直接指定该缓冲区的大小(只需要设置管道流类中的PIPE_SIZE属性的值)。当生产者生产出数据后,只需要将数据写入管道中,消费者只需要从管道中读取所需要的数据。利用管道的这种机制,可以将一个线程的输出结果直接连接到另一个线程的输入端口,实现两者之间的数据直接传送。
管道的连接方式:
方法一:通过构造函数直接将某一个程序的输出作为另一个程序的输入,在定义对象时指明目标管道对象
PipedInputStream pInput=new PipedInputStream();
PipedOutputStream pOutput= new PipedOutputStream(pInput);
方法二:利用双方类中的任一个成员函数 connect()相连接
PipedInputStream pInput=new PipedInputStream();
PipedOutputStream pOutput= new PipedOutputStream();
pinput.connect(pOutput);
管道的输入与输出:
输出管道对象调用write()成员函数输出数据(即向管道的输入端发送数据);而输入管道对象调用read()成员函数可以读起数据(即从输出管道中获得数据)。这主要是借助系统所提供的缓冲机制来实现的。
代码如下:
import java.io.*;
public class PipedIO // 程序运行后将sendFile文件的内容拷贝到receiverFile文件中
{
public static void main(String args[]) {
try {
// 构造读写的管道流对象
PipedInputStream pis = new PipedInputStream();
PipedOutputStream pos = new PipedOutputStream();
// 实现关联
pos.connect(pis);
// 构造两个线程,并且启动。
new Sender(pos, "c:\\text2.txt").start();
new Receiver(pis, "c:\\text3.txt").start();
} catch (IOException e) {
System.out.println("Pipe Error" + e);
}
}
}
//线程接收
class Receiver extends Thread {
PipedInputStream pis;
File file;
// 构造方法
Receiver(PipedInputStream pis, String fileName) {
this.pis = pis;file = new File(fileName);
}
// 线程运行
public void run() {
try {
// 写文件流对象
FileOutputStream fs = new FileOutputStream(file);int data;
// 从管道末端读
while ((data = pis.read()) != -1) {
// 写入本地文件
fs.write(data);
}
pis.close();
} catch (IOException e){
System.out.println("Receiver Error" + e);
}
}
}
// 线程发送
class Sender extends Thread {
PipedOutputStream pos;
File file;
// 构造方法
Sender(PipedOutputStream pos, String fileName) {
this.pos = pos;
file = new File(fileName);
}
// 线程运行方法
public void run() {
try {
// 读文件内容
FileInputStream fs = new FileInputStream(file);
int data;
while ((data = fs.read()) != -1) {
// 写入管道始端
pos.write(data);
}
pos.close();
} catch (IOException e) {
System.out.println("Sender Error" + e);
}
}
}