我正在做一些关于多线程的实验。
当程序运行到输出部分时,(使用java.io.FileWriter
)
有时它可以快速通过,
但有时它只是停留在那里。
是FileWriter
的问题吗?
这是简化的代码:
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
public class Test extends Thread {
private int _id;
public Test(int id) {
_id = id;
}
@Override
public void run() {
long start = System.currentTimeMillis();
for (int i = 0; i < 10000; i++) {
try (FileWriter fw = new FileWriter(new File(_id + ".txt"))) {
fw.write("hello!");
} catch (IOException e) {
System.err.println("Something wrong.");
}
}
System.out.println(_id + ": " + (System.currentTimeMillis() - start));
}
public static void main(String[] args) {
for (int i = 0; i < 10; i++) {
new Test(i).start();
}
}
}
这是我的结果:
7: 3820 9: 3878 2: 3965 8: 3956 0: 4058 6: 4097 5: 4111 3: 4259 1: 4354 4: 4369
9: 4703 7: 4748 5: 4891 2: 4994 4: 5065 3: 5672 1: 5804 0: 5805 8: 5925 6: 6042
1: 4495 9: 5265 6: 5551 2: 5651 5: 5676 8: 5697 3: 5917 0: 6001 7: 6002 4: 6314
我跑了三次,为什么经过的时间不同?
它是FileWriter
的问题还是文件系统的?
答案 0 :(得分:1)
你至少有两个问题:
open()
,write()
,(可能flush()
,最后close()
;至少300k系统调用!FileWriter
个对象,100k File
个对象; gc需要处理所有这些;并且由于gc本身在一个线程中运行并且像任何其他线程一样进行调度,因此它会或多或少地运行。因此,您的程序问题比操作系统相关问题更多... JIT在这里无法为您做任何事情。
另外,既然你使用Java 7,你应该考虑使用Files.newBufferedWriter()
- 每个线程只使用一次,当然不是10000次!
进一步注意“系统调用问题”:至少在Unix系统上,但其他操作系统可能工作原理相同,每次你进行系统调用,你的进程必须进入内核模式执行系统调用;这不是免费的。即使在现代系统上,成本并不那么重要,但它仍远远高于而不是必须使用用户 - &gt; kernel-&gt;用户。
run()
,并随着时间的推移进行优化。
答案 1 :(得分:0)
为什么经过的时间不同?是FileWriter的问题还是文件系统的?
打开和关闭文件非常昂贵。您的瓶颈很可能出在您的操作系统或硬盘中。即代码不能很好地扩展。您很可能只有不到10个CPU,所以只有那么多线程同时运行。当你的代码不能很好地扩展并且系统过载时,你会得到很大的性能结果。
问题在于您的程序试图使系统过载。使用更多的CPU可以提供更强大的处理能力,并且您正在使用它来从10个不同的方面锤击您的操作系统。