从多个线程写入多个文本文件

时间:2014-05-18 12:16:27

标签: java multithreading io

我正在做一些关于多线程的实验。

当程序运行到输出部分时,(使用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的问题还是文件系统的?

2 个答案:

答案 0 :(得分:1)

你至少有两个问题:

  • 你让太多的系统调用;基本上,对于每个线程的一个循环,您执行open()write(),(可能flush(),最后close();至少300k系统调用!
  • 您创建了100k FileWriter个对象,100k File个对象; gc需要处理所有这些;并且由于gc本身在一个线程中运行并且像任何其他线程一样进行调度,因此它会或多或少地运行。

因此,您的程序问题比操作系统相关问题更多... JIT在这里无法为您做任何事情。

另外,既然你使用Java 7,你应该考虑使用Files.newBufferedWriter() - 每个线程只使用一次,当然不是10000次!


进一步注意“系统调用问题”:至少在Unix系统上,但其他操作系统可能工作原理相同,每次你进行系统调用,你的进程必须进入内核模式执行系统调用;这不是免费的。即使在现代系统上,成本并不那么重要,但它仍远远高于而不是必须使用用户 - &gt; kernel-&gt;用户。


好吧,好吧,我撒了一点; JIT确实启动但它只会优化用户方面的事情。 JT将在方法执行10k后开始优化,此处为run(),并随着时间的推移进行优化。

答案 1 :(得分:0)

  

为什么经过的时间不同?是FileWriter的问题还是文件系统的?

打开和关闭文件非常昂贵。您的瓶颈很可能出在您的操作系统或硬盘中。即代码不能很好地扩展。您很可能只有不到10个CPU,所以只有那么多线程同时运行。当你的代码不能很好地扩展并且系统过载时,你会得到很大的性能结果。

问题在于您的程序试图使系统过载。使用更多的CPU可以提供更强大的处理能力,并且您正在使用它来从10个不同的方面锤击您的操作系统。