2017-10-09 249 views
1

我有一个不断生成数据并将其写入到其自己线程上的ByteArrayOutputStream的类。我有第二个线程获取对此ByteArrayOutputStream的引用。我希望第二个线程读取任何数据(并清空)ByteArrayOutputStream,然后在没有得到任何字节和睡眠时停止。睡眠后,我想让它尝试获取更多数据并再次清空。从ByteArrayOutputStream中读取数据并将其写入

我在网上看到的例子说使用PipedOutputStream。如果我的第一个线程使ByteArrayOutputStream从一个单独的可重用库中可用于外界,我看不到如何将inputStream连接到它。

如何设置PipedInputStream将其连接到ByteArrayOutputStream以从上面读取它?另外,当从ByteArrayOutputStream读取最后一个块时,是否会看到bytesRead == -1,指示outputStream何时从第一个线程关闭?

非常感谢, 麦克

回答

3

刻录到PipedOutputStream直接(即,不使用ByteArrayOutputStream的话)。它们都扩展为OutputStream,因此具有相同的接口。

PipedOutputStreamPipedInputStream中有connect方法用于将两个管道连接在一起,或者您可以使用其中一个构造函数创建一对。

写入PipedOutputStreamPipedInputStream缓冲区已​​满将阻止,并从PipedInputStream读取时,缓冲区为空会阻塞,因此,生产者线程将休眠(块),如果它变得“超前”消费的反之亦然。

在重新检查缓冲区之前,阻塞线程等待1000ms之后,所以最好在写入完成后刷新输出(如果它正在睡眠,这将唤醒读取器)。

当您关闭生产者线程中的输出流时,您的输入流将会看到EOF(bytesRead == -1)。

import java.io.*; 
import java.util.concurrent.ExecutorService; 
import java.util.concurrent.Executors; 

public class PipeTest { 
    public static void main(String[] args) throws IOException { 
     PipedOutputStream out = new PipedOutputStream(); 
     // Wire an input stream to the output stream, and use a buffer of 2048 bytes 
     PipedInputStream in = new PipedInputStream(out, 2048); 

     ExecutorService executor = Executors.newCachedThreadPool(); 

     // Producer thread. 
     executor.execute(() -> { 
      try { 
       for (int i = 0; i < 10240; i++) { 
        out.write(0); 
        // flush to wake the reader 
        out.flush(); 
       } 
       out.close(); 
      } catch (IOException e) { 
       throw new UncheckedIOException(e); 
      } 
     }); 

     // Consumer thread. 
     executor.execute(() -> { 
      try { 
       int b, read = 0; 
       while ((b = in.read()) != -1) { 
        read++; 
       } 
       System.out.println("Read " + read + " bytes."); 
      } catch (IOException e) { 
       throw new UncheckedIOException(e); 
      } 
     }); 

     executor.shutdown(); 
    } 
} 
+0

这太棒了。感谢您为我清理! – Mike

+0

嗨teppic,我已经编码了所有这一切,似乎我的生产者线程必须填充连接的PipedInputStream的缓冲区之前,它的读取踢。这是有道理的,但这是否意味着,如果我的制作人从麦克风输出数据,会有一些时期会失去投入?我应该考虑某种“双缓冲”来处理这个问题吗? – Mike

+1

尝试在每次写入后清空输出流。 – teppic

相关问题