4

是否有 GZIPOutputStream 的实现可以在单独的线程中完成繁重的工作(压缩+写入磁盘)?

我们不断写入大量 GZIP 压缩数据。我正在寻找一个可以代替 GZIPOutputStream 的替代品。

4

2 回答 2

5

您可以写入 PipedOutputStream 并拥有一个线程来读取 PipedInputStream 并将其复制到您喜欢的任何流中。

这是一个通用的实现。您给它一个 OutputStream 来写入,它返回一个 OutputStream 供您写入。

public static OutputStream asyncOutputStream(final OutputStream out) throws IOException {
    PipedOutputStream pos = new PipedOutputStream();
    final PipedInputStream pis = new PipedInputStream(pos);
    new Thread(new Runnable() {
        @Override
        public void run() {
            try {
                byte[] bytes = new byte[8192];
                for(int len; (len = pis.read(bytes)) > 0;)
                    out.write(bytes, 0, len);
            } catch(IOException ioe) {
                ioe.printStackTrace();
            } finally {
                close(pis);
                close(out);
            }
        }
    }, "async-output-stream").start();
    return pos;
}

static void close(Closeable closeable) {
    if (closeable != null) try {
        closeable.close();
    } catch (IOException ignored) {
    }
}
于 2012-09-21T14:10:50.920 回答
1

我发布了一些完全符合您要求的代码。让我感到沮丧的是,Java 不会自动跨多个线程进行这样的管道调用,以便重叠计算、压缩和磁盘 I/O:

https://github.com/lukehutch/PipelinedOutputStream

此类将写入 a 拆分OutputStream为单独的生产者和消费者线程(实际上,为消费者启动一个新线程),并在它们之间插入一个阻塞的有界缓冲区。缓冲区之间有一些数据复制,但这是尽可能高效地完成的。

您甚至可以将其分层两次,以便在 gzip 压缩之外的单独线程中进行磁盘写入,如README.md.

于 2019-10-27T05:03:58.887 回答