有多少文件读取器可以同时从同一个文件中读取?

时间:2014-05-30 22:36:59

标签: java file-io

我有一个巨大的25GB CSV文件。我知道文件中有大约5亿条记录。

我想对数据做一些基本的分析。没什么太花哨的。

我不想使用Hadoop / Pig,至少还没有。

我编写了一个java程序来同时进行我的分析。这就是我在做的事情。

class MainClass {
 public static void main(String[] args) {
  long start = 1;
  long increment = 10000000;
  OpenFileAndDoStuff a = new OpenFileAndDoStuff[50];
  for(int i=0;i<50;i++) {
    a[i] = new OpenFileAndDoStuff("path/to/50GB/file.csv",start,start+increment-1);
    a[i].start();
    start += increment;
  } 
  for(OpenFileAndDoStuff obj : a) {
     obj.join();
  }
  //do aggregation 
 }
}

class OpenFileAndDoStuff extends Thread {
  volatile HashMap<Integer, Integer> stuff = new HashMap<>();
  BufferedReader _br;
  long _end;
  OpenFileAndDoStuff(String filename, long startline, long endline) throws IOException, FileNotFoundException {
    _br = new BufferedReader(new FileReader(filename));
    long counter=0;
    //move the bufferedReader pointer to the startline specified
    while(counter++ < start) 
     _br.readLine();
    this._end = end;
  }
  void doStuff() {
    //read from buffered reader until end of file or until the specified endline is reached and do stuff
  }
  public void run() {
    doStuff();
  }
  public HashMap<Integer, Integer> getStuff() {
    return stuff;
  } 
}

我想这样做我可以打开50个bufferedReaders,所有读取并行读取1000万行chucks,一旦所有这些都完成了他们的东西,我会聚合它们。

但是,我遇到的问题是,即使我要求50个线程启动,一次只启动两个并且可以一次从文件中读取。

有没有办法可以让所有50个人打开文件并同时阅读?为什么我一次只能限制两个读者?

该文件位于Windows 8计算机上,而java也位于同一台计算机上。

有什么想法吗?

2 个答案:

答案 0 :(得分:2)

以下是类似帖子:Concurrent reading of a File (java preffered)

  

这里最重要的问题是您的案例中的瓶颈

     

如果瓶颈是您的磁盘IO ,那么您在软件部分可以做的事情就不多了。并行化计算只会使事情变得更糟,因为同时从不同部分读取文件会降低磁盘性能。

     

如果瓶颈是处理能力,并且您有多个CPU核心,那么您可以利用启动多个线程来处理文件的不同部分。您可以安全地创建多个InputStreams或Readers来并行读取文件的不同部分(只要您没有超过操作系统对打开文件数量的限制)。您可以将工作分成任务并并行运行

有关与FileInputStream并行读取单个文件的示例,请参阅引用的帖子,根据这些基准测试,这应该比使用BufferedReader快得多:http://nadeausoftware.com/articles/2008/02/java_tip_how_read_files_quickly#FileReaderandBufferedReader

答案 1 :(得分:1)

我看到的一个问题是,当要求线程读取时,例如,行80000000到90000000,您仍在读取前80000000行(并忽略它们)。

也许尝试java.io.RandomAccessFile

为此,您需要所有行都具有相同的字节数。如果您无法调整文件的结构,那么这将不是一个选项。但是,如果可以,这应该允许更大的并发性。