我正在尝试在多线程环境中创建多个zip文件(实际上我尝试使用提供16个线程的FixedThreadPool ExecutorService来编写大约400个zip文件)。每个zip文件都可能包含数千个其他zip文件。
不幸的是,大约两分钟后,我的java进程(Windows 64bit上的jdk1.8.0_60_x64)似乎最终导致内存泄漏。虽然堆(根据Java Mission Control)仅使用大约1 GB(实际上在500 MB和1 GB之间),但java进程总共使用大约40 GB的机器内存(似乎使用了大量本机内存)。当进程/我的系统几乎停止工作时(我没有那么多内存),这个数字不断增加并且接着不断增加。
经过一些研究后,我发现可以使用一个相当小的主要方法来模拟行为:
public static void main(String[] args) throws Throwable {
for (int k = 0; k < 16; k++) {
new Thread(Integer.toString(k)) {
@Override
public void run() {
try {
long bytes = 0;
ZipOutputStream zos = new ZipOutputStream(new BufferedOutputStream(new FileOutputStream(new File(getName() + ".tmp"))));
zos.setLevel(Deflater.NO_COMPRESSION);
Random rand = new SecureRandom();
for (int i = 0; i < 65535; i++) {
zos.putNextEntry(new ZipEntry("" + i));
ZipOutputStream inner = new ZipOutputStream(zos);
for (int j = 0; j < 10; j++) {
byte[] b = new byte[512];
bytes += b.length;
rand.nextBytes(b);
inner.putNextEntry(new ZipEntry("" + j));
inner.write(b);
inner.closeEntry();
}
inner.finish();
inner.flush();
zos.closeEntry();
zos.flush();
if (i % 1000 == 0) {
System.err.println(getName() + ": " + i + " (" + bytes + ") bytes");
}
}
zos.flush();
zos.close();
}
catch (Exception e) {
e.printStackTrace();
}
}
}.start();
}
}
我的代码有什么问题吗?可能。
在这么多线程中使用I / O操作是个坏主意吗?我真的不确定(实际上我想获得性能,而不是松散的性能)。但另一方面,如果我省略了所有的zip内容,只需在更多线程中写入FileOutputStream就不会出现这样的问题。 zip压缩条目的开销会增加那么多吗?
使用内部 ZipOutputStream有什么问题吗?据我所知,我不能为这个类调用close(),因为它也会关闭名为 zos 的外部流。相反,我打电话给 finish()。