【发布时间】:2014-10-08 03:22:03
【问题描述】:
我正面临一个有点奇怪的情况。
我正在将一个大小约为 500MB 的文件从 FileInputStream 复制到 FileOutputStream。 它进展顺利(大约需要 500 毫秒)。当我在 FIRST 时间关闭此 FileOutputStream 时,大约需要 1 毫秒。
但问题来了,当我再次运行此程序时,每次连续关闭大约需要 1500-2000 毫秒! 当我删除这个文件时,持续时间下降到 1 毫秒。
我缺少一些基本的java.io 知识吗?
这似乎与操作系统有关。我在 ArchLinux 上运行(在 Windows 7 上运行的相同代码一直都在 20 毫秒以下)。请注意,它是否在 OpenJDK 或 Oracle 的 JDK 中运行并不重要。硬盘是带有 ext4 文件系统的固态硬盘。
这是我的测试代码:
public void copyMultipleTimes() throws IOException {
copy();
copy();
copy();
new File("/home/d1x/temp/500mb.out").delete();
copy();
copy();
// Runtime.getRuntime().exec("sync") => same results
// Thread.sleep(30000) => same results
// combination of sync & sleep => same results
copy();
}
private void copy() throws IOException {
FileInputStream fis = new FileInputStream("/home/d1x/temp/500mb.in");
FileOutputStream fos = new FileOutputStream("/home/d1x/temp/500mb.out");
IOUtils.copy(fis, fos); // copyLarge => same results
// copying takes always the same amount of time, only close "enlarges"
fis.close(); // input stream close this is always fast
// fos.flush(); // has no effect
// fos.getFD().sync(); // Solves the problem but takes ~2.5s
long start = System.currentTimeMillis();
fos.close();
System.out.println("OutputStream close took " + (System.currentTimeMillis() - start) + "ms");
}
那么输出是:
OutputStream close took 0ms
OutputStream close took 1951ms
OutputStream close took 1934ms
OutputStream close took 1ms
OutputStream close took 1592ms
OutputStream close took 1727ms
【问题讨论】:
-
在 Ubuntu 13.10 上运行的 Java7 具有相同的行为。
-
你能尝试在
close之前显式地flushfos(当然在long start = System.currentTimeMillis();之前)吗? -
这确实似乎是特定于操作系统的,因为我无法在 Win7 下重现它(得到不一致的结果)
-
这是真的克里斯,但“经典”硬盘上的时间是一样的。
-
如果它与 Java 有任何关系,我会感到惊讶。用'cp'试试。我希望你会得到非常相似的结果。这很可能与固态硬盘的工作方式有关。