4

我正在创建线程来读取 java 中的文件。当我创建 2 个线程时,每个线程读取整个文件,而我希望它们读取文件的不同部分。我尝试放入 sleep()、join()、yield() 但在包含它们之后它只是减慢了读取速度。

public class MyClass implements Runnable {

    Thread thread;
    public MyClass(int numOfThreads) {
        for(int i=0;i < numOfThreads; i++) {
            thread = new Thread(this);
            thread.start();
        }
    }

    public void run() {
        readFile();
    }
}

在 readFile 中,在 while 循环中(逐行读取)我调用了 sleep()/yield()。如何让线程读取文件的不同部分?

更新了用于读取文件的方法...

public synchronized void readFile() {
    try {
        String str;
        BufferedReader buf = new BufferedReader(new FileReader("read.txt");
        while ((line = buf.readLine()) != null) {
            String[] info = str.split(" ");
            String first name = info[0];
            String second name = info[1];
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
            }
        }  catch (IOException e) {
        System.out.println("Error : File not found");
        e.printStackTrace();
    }
}
4

2 回答 2

25

我想你在想用这样的多线程读取文件会比用一个线程读取要快。这几乎肯定是错误的。线程在使用多个内核或处理器的 CPU 密集型任务上获得更好的性能。但文件读取不是 CPU 密集型任务。

操作系统使用磁盘控制器以磁盘接口的全带宽读取字节。对于几乎任何硬件组合,速度都受磁盘(读取和/或寻道时间)、它的控制器、它的 DMA 接口或总线的限制,而不是由 CPU 决定。CPU 很容易让磁盘控制器保持 100% 繁忙,即使是多个控制器用于不同的磁盘。如果您需要证明这一点,请启动一个大文件副本并观察 CPU 利用率。不会很高。

因此,在您的多个线程中,一次只能运行一个,从而增加了单线程计算的开销。

慢速文件传输是缓冲。为了获得灵活性,i/o 库最终可以将每个字符缓冲 2 次甚至 3 次。

Java NIO 库旨在尽可能多地消除这种开销。例如见这篇文章。类似的还有很多。我的经验是,精心编写的 NIO 阅读器将使用硬件的大部分可用性能。

有一个警告:如果您设置了重型病毒检查器来扫描您正在阅读的文件类型,它可能会使读取 CPU 受限。在这种不寻常的情况下,您可能会通过多线程获得提升,具体取决于检查器架构。在这种情况下,您会找到总文件大小 S 并让线程 k=0,1,..,n-1 从偏移量 kS/n 读取到 (k+1)S/n - 1 (通过seek向右偏移量和跟踪每个线程中读取的字节数)。然而,我仍然强烈怀疑额外的磁头寻道时间和随机访问的其他影响将抵消在多线程中运行病毒检查程序的任何优势。

于 2013-09-24T02:28:15.253 回答
-1

在您的程序中 string.split(" ") 会导致运行时速度变慢。自己写,速度提升6倍。这样的事情会有所帮助:

int index = vcf_record_string.indexOf("\t");
vcf_record_string.substring(0, index)

如果您的系统支持高吞吐量 I/O,您可以这样做: How to read a file using multiple threads in Java when a high throughput(3GB/s) file system is available

于 2016-11-04T22:18:59.610 回答