我有一个巨大的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也位于同一台计算机上。
有什么想法吗?
答案 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行(并忽略它们)。
为此,您需要所有行都具有相同的字节数。如果您无法调整文件的结构,那么这将不是一个选项。但是,如果可以,这应该允许更大的并发性。