2012-07-17 67 views
1

目前,我有一个解析器的设置,将通过约2万条记录的CSV文件解析。然后我应用一些过滤算法来清除要包含/排除的记录。最后将所有内容写回新的csv文件。Java解析器使用多线程

我已经做了一些基准测试,它原来是写数据到CSV是非常昂贵和过滤,并在同一时间附加到文件时造成巨大的减速。我想知道是否可以执行我所有的过滤,将行写入队列中,然后让第二个进程在队列已满或所有过滤完成时自行执行所有写入。

所以基本上总结:

Read line 
Decide whether to discard or keep 
if I'm keeping the file, add it to the "Write Queue" 
Check if the write queue is full, if so, start the new process that will begin writing 
Continue filtering until completed 

感谢您的帮助!

编辑: 的方式我写如下:

FileWriter fw = new FileWriter("myFile.csv"); 
BufferedWriter bw = new BufferedWriter(fw); 
while(read file...) { 
    //perform filters etc... 
    try { 
     bw.write(data.trim()); 
     bw.newLine(); 

    }catch(IOException e) { 
     System.out.println(e.getMessage()); 
    } 
+0

你介意张贴你如何写出CSV文件的一些代码? – Shawn 2012-07-17 03:28:47

+0

我用Python做这个确切的方法,并在完全不同的线程中读,写和处理。这是可能的。 – Blender 2012-07-17 03:30:26

+0

@Blender你的Python解析器执行的效率是多少? – 1337holiday 2012-07-17 03:47:53

回答

3

读取和写入过程两个I/O限制(寻求到磁盘上的部门和执行磁盘I/O,以/来自内存),而过滤进程完全是CPU绑定的。这是多线程的好选择。

我会用三个线程:阅读,过滤和写作。这需要两个队列,但没有理由在处理之前等待队列变满。

  • 阅读器线程从文件中读取数据并将行附加到传入队列中。
  • 过滤器线程从传入队列需要的行,并写入那些过滤器传递到传出队列。
  • 写入线程从传出队列获取行并将它们写入新文件。

请确保使用缓冲读取器和写入器,以尽量减少读写器线程之间的争用。假设过滤过程相当简单,您希望尽量减少磁盘搜索,因为这将成为瓶颈。

+0

完美!我很可能会实施这一点。 – 1337holiday 2012-07-17 04:11:40

+0

+1,但有一种机制可以读取或写入,但不能同时进行。这样,你就不会有两个线程争夺相同的磁盘头。信号量在这里是一个很好的选择:读者线程读取一堆信息,然后释放它,以便作者可以接受它,然后将其释放回读者。你必须有一些启发式的方法,以便一个线程不会释放信号量而只是立即重新获得它。 – yshavit 2012-07-17 04:12:10

+0

@yshavit - 为什么不使用磁盘作为信号量?它具有低开销,并且工作得很好。当然,如果您一次读取多个数据块,但只有在保证文件存储在连续数据块中的情况下,才可以获得略好的性能。另外,如果您正在从正在读取的磁盘写入其他磁盘,则会序列化可同时运行的进程。尽管如此,这是需要考虑的事情。 – 2012-07-17 04:33:10

0

你可能想,除非你有使用Spring的任何约束考虑使用Spring Batch的。