- 在学习java的I/O流时我们知道 所有源自Inputstream或者Reader的子类都有一个read()方法。API中说该方法是阻塞式方法:在输入数据可用、检测到流末尾或者抛出异常前,此方法一直阻塞。
- 下面我们通过管道流来观察这一现象。
类 PipedInputStream 类PipedOutputStream
管道输入流应该连接到管道输出流;管道输入流提供要写入管道输出流的所有数据字节。通常,数据由某个线程从 PipedInputStream 对象读取,并由其他线程将其写入到相应的 PipedOutputStream。不建议对这两个对象尝试使用单个线程,因为这样可能死锁线程。管道输入流包含一个缓冲区,可在缓冲区限定的范围内将读操作和写操作分离开。如果向连接管道输出流提供数据字节的线程不再存在,则认为该管道已损坏。
实现Runnable接口的类 完成输入流的加载
class Input implements Runnable { PipedInputStream PIStream = null; public Input(PipedInputStream pIStream) { super(); PIStream = pIStream; } @Override public void run() { // TODO Auto-generated method stub int len = 0; byte[] buf = new byte[1024]; try { System.out.println("read方法阻塞"); while ((len = PIStream.read(buf)) != -1) { System.out.println("读到的数据:" + new String(buf)); } System.out.println("read阻塞结束"); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } finally { //避免空指针异常 关闭 管道输入流 if (PIStream != null) { try { PIStream.close(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } } }
实现Runnable接口的类 完成输出流的加载
class Output implements Runnable { PipedOutputStream POStream = null; public Output(PipedOutputStream pOStream) { super(); POStream = pOStream; } @Override public void run() { // TODO Auto-generated method stub try { POStream.write("管道输出流数据来了".getBytes()); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } finally { if (POStream != null) { try { POStream.close(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } } }
在主类中完成对 两个辅助类的分别调用可以观察实现结果
import java.io.IOException; import java.io.PipedInputStream; import java.io.PipedOutputStream; public class PipedStream { /** * 1、我们知道输入流的read()方法会有阻塞情况发生 * 2、通过下面的这个例子说明一下多线程解决这个阻塞的发生 * 3、另外API中说到:管道输入流应该连接到管道输出流; * 数据由某个线程从 PipedInputStream 对象读取, * 并由其他线程将其写入到相应的 PipedOutputStream。 * 不建议对这两个对象尝试使用单个线程,因为这样可能死锁线程。 * * 4、通过操作我们可以发现当单独启动第一条线程时Thread(new Input(PIStream)).start()时 * 会发生read()方法的阻塞 * @param args * @throws IOException */ public static void main(String[] args) throws IOException { // TODO Auto-generated method stub PipedInputStream PIStream = new PipedInputStream(); PipedOutputStream POStream = new PipedOutputStream(); //使PIStream输入流连接到管道输出流 POStream。 //如果此对象已经连接到其他某个管道输出流,则抛出 IOException。 PIStream.connect(POStream); new Thread(new Input(PIStream)).start(); new Thread(new Output(POStream)).start(); } }