2012-07-17 33 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的。