是否有 GZIPOutputStream 的实现可以在单独的线程中完成繁重的工作(压缩+写入磁盘)?
我们不断写入大量 GZIP 压缩数据。我正在寻找一个可以代替 GZIPOutputStream 的替代品。
是否有 GZIPOutputStream 的实现可以在单独的线程中完成繁重的工作(压缩+写入磁盘)?
我们不断写入大量 GZIP 压缩数据。我正在寻找一个可以代替 GZIPOutputStream 的替代品。
您可以写入 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) {
}
}
我发布了一些完全符合您要求的代码。让我感到沮丧的是,Java 不会自动跨多个线程进行这样的管道调用,以便重叠计算、压缩和磁盘 I/O:
https://github.com/lukehutch/PipelinedOutputStream
此类将写入 a 拆分OutputStream
为单独的生产者和消费者线程(实际上,为消费者启动一个新线程),并在它们之间插入一个阻塞的有界缓冲区。缓冲区之间有一些数据复制,但这是尽可能高效地完成的。
您甚至可以将其分层两次,以便在 gzip 压缩之外的单独线程中进行磁盘写入,如README.md
.