管道流:管道一头读数据,另一头写数据,这就涉及到多线程的问题,如何保证读取一致性
管道输入流应该连接到管道输出流;管道输入流提供要写入管道输出流的所有数据字节。通常,数据由某个线程从 PipedInputStream 对象读取,并由其他线程将其写入到相应的 PipedOutputStream。不建议对这两个对象尝试使用单个线程,因为这样可能死锁线程。管道输入流包含一个缓冲区,可在缓冲区限定的范围内将读操作和写操作分离开。如果向连接管道输出流提供数据字节的线程不再存在,则认为该管道已损坏。
如何将管道输入流与管道输出流结合在一起?
第一种方法:使用管道输入流的构造函数
PipedInputStream(PipedOutputStream src)
创建 PipedInputStream,使其连接到管道输出流 src。
第二种方法:使用管道输入流的connect方法
connect(PipedOutputStream src)
使此管道输入流连接到管道输出流 src。
package newFeatures8;
import java.io.IOException;
import java.io.PipedInputStream;
import java.io.PipedOutputStream;
public class PipedIODemo{
public static void main(String[] args) throws IOException {
PipedInputStream in=new PipedInputStream();
PipedOutputStream out=new PipedOutputStream();
in.connect(out);
Read read=new Read(in);
Write write=new Write(out);
//谁先抢到cup的执行权不重要
new Thread(read).start();
new Thread(write).start();
}
}
class Read implements Runnable{
private PipedInputStream in;
public Read(PipedInputStream in){
if (in!=null) {
this.in=in;
}else{
throw new NullPointerException("传入对象为空");
}
}
@Override
public void run() {
try {
byte[] buf=new byte[1024];//1k:512字符
System.out.println("读取前没有数据就阻塞");
int len=in.read(buf);
System.out.println("读到数据阻塞结束!");
//读到多少写多少
//从字节数组里获取指定长度的子数组,然后构成新的字符串
String content=new String(buf,0,len);
System.out.println(content);
} catch (Exception e) {
throw new RuntimeException("管道输入流失败");
}finally {
try {
if(in!=null)
in.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
class Write implements Runnable{
private PipedOutputStream out;
public Write(PipedOutputStream out){
if (out!=null) {
this.out=out;
}else{
throw new NullPointerException("传入对象为空");
}
}
@Override
public void run() {
try {
System.out.println("开始写入数据,等待6秒后");
Thread.sleep(6000);
//注意:写出的数据写到哪去了呢?写到了与之关联的管道输入流里去了
out.write("piped lai la".getBytes());
} catch (Exception e) {
throw new RuntimeException("管道输出流失败");
}finally {
try {
if(out!=null)
out.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}