简体   繁体   English

在写入时从ByteArrayOutputStream读取

[英]Read from ByteArrayOutputStream while it's being written to

I have a class that is constantly producing data and writing it to a ByteArrayOutputStream on its own thread. 我有一个不断生成数据并在其自己的线程上将其写入ByteArrayOutputStream的类。 I have a 2nd thread that gets a reference to this ByteArrayOutputStream. 我有一个第二个线程获取对此ByteArrayOutputStream的引用。 I want the 2nd thread to read any data (and empty) the ByteArrayOutputStream and then stop when it doesn't get any bytes and sleep. 我希望第二个线程读取ByteArrayOutputStream的任何数据(并清空),然后在没有任何字节和睡眠时停止。 After the sleep, I want it to try to get more data and empty it again. 睡眠后,我希望它尝试获取更多数据并再次清空它。

The examples I see online say to use PipedOutputStream. 我在网上看到的例子说使用PipedOutputStream。 If my first thread is making the ByteArrayOutputStream available to the outside world from a separate reusable library, I don't see how to hook up the inputStream to it. 如果我的第一个线程是从一个单独的可重用库使ByteArrayOutputStream可用于外部世界,我不知道如何将inputStream连接到它。

How would one setup the PipedInputStream to connect it to the ByteArrayOutputStream to read from it as above? 如何设置PipedInputStream将其连接到ByteArrayOutputStream以从上面读取它? Also, when reading the last block from the ByteArrayOutputStream, will I see bytesRead == -1, indicating when the outputStream is closed from the first thread? 另外,当从ByteArrayOutputStream读取最后一个块时,我是否会看到bytesRead == -1,指示outputStream何时从第一个线程关闭?

Many thanks, Mike 非常感谢,迈克

Write to the PipedOutputStream directly (that is, don't use a ByteArrayOutputStream at all). 直接写入PipedOutputStream (也就是说,根本不要使用ByteArrayOutputStream )。 They both extend OutputStream and so have the same interface. 它们都扩展了OutputStream ,因此具有相同的接口。

There are connect methods in both PipedOutputStream and PipedInputStream that are used to wire two pipes together, or you can use one of the constructors to create a pair. PipedOutputStreamPipedInputStream中都有connect方法,用于将两个管道连接在一起,或者您可以使用其中一个构造函数来创建一对。

Writes to the PipedOutputStream will block when the buffer in the PipedInputStream fills up, and reads from the PipedInputStream will block when the buffer is empty, so the producer thread will sleep (block) if it gets "ahead" of the consumer and vice versa. PipedInputStream的缓冲区填满时,对PipedOutputStream写入将被阻塞,并且当缓冲区为空时, PipedInputStream读取将被阻塞,因此如果生产者线程“超前”消费者,则生产者线程将休眠(阻塞),反之亦然。

After blocking the threads wait for 1000ms before rechecking the buffer, so it's good practice to flush the output after writes complete (this will wake the reader if it is sleeping). 在重新检查缓冲区之前阻塞线程等待1000ms后,所以在写入完成后刷新输出是个好习惯(这会在读取器休眠时唤醒它)。

Your input stream will see the EOF (bytesRead == -1) when you close the output stream in the producer thread. 在生产者线程中关闭输出流时,输入流将看到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();
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM