2013-04-23 108 views
5

一直在尋找一段時間,現在我對這個問題有點困惑。我希望能夠接受一個輸入流並分段讀取它。段不互相交互,它們只是要從上載的文件中插入或更新數據庫中的值。是否可以通過設置段大小併發讀取輸入流,然後在轉出新線程以處理轉換和插入/更新之前跳過前進?Java:併發讀取InputStream

本質上來說,文件是一個ID的列表(每行一個ID),儘管如果我可以指定一個分隔符會更好。某些文件可能非常龐大,所以我想要將數據處理並轉換爲段,以便在插入/更新數據庫之後可以釋放JVM內存。這可能嗎?如果有的話,是否有任何圖書館已經這樣做?

在歡呼聲中提前致謝,

Alexei Blue。

回答

6

一個好的方法可能是讓一個閱讀器讀取塊,然後將每個塊從線程池移交給工作線程。鑑於這些將被插入到數據庫中,與讀取輸入相比,插入將是緩慢的部分,因此單個線程應該足以進行讀取。

下面是一個示例,將System.in的每行處理交給工作線程處理。如果您在單個事務中執行大量插入操作,則數據庫插入的性能要好得多,因此,傳遞一組1000行代碼將比傳遞單行代碼更好,如示例中所示。

import java.io.BufferedReader; 
import java.io.IOException; 
import java.io.InputStreamReader; 
import java.util.concurrent.ExecutorService; 
import java.util.concurrent.Executors; 

public class Main { 
    public static class Worker implements Runnable { 
     private final String line; 

     public Worker(String line) { 
      this.line = line; 
     } 

     @Override 
     public void run() { 
      // Process line here. 
      System.out.println("Processing line: " + line); 
     } 
    } 

    public static void main(String[] args) throws IOException { 
     // Create worker thread pool. 
     ExecutorService service = Executors.newFixedThreadPool(4); 

     BufferedReader buffer = new BufferedReader(new InputStreamReader(System.in)); 
     String line; 

     // Read each line and hand it off to a worker thread for processing. 
     while ((line = buffer.readLine()) != null) { 
      service.execute(new Worker(line)); 
     } 
    } 
} 
+0

嗨埃德感謝^。^所以,如果我讀1000行到一個StringBuffer,然後通過這個開了個工作線程的例子/更新的數據庫,你認爲這會是一個好方法嗎? :) – 2013-04-23 09:11:45

+0

這很可能是最好的1000行讀入'列表'或'的String []'。如果你讀它們放入一個'StringBuffer'那麼它會是一個字符串,你需要分析出各行第二次。 – 2013-04-23 11:15:41

1

我不認爲你可以同時讀取InputStream。這就是合同定義讀取,重置和標記的原因 - 這個想法是流在內部跟蹤已讀和未讀的內容。

如果您正在閱讀文件,只需打開多個流。您可以使用skip()方法爲其他線程提前移動標記以避免重複的行處理。 BufferedReader也可能有所幫助,因爲它提供了閱讀line by line

+0

呀緩衝讀卡器+跳過目前我做的方式,需要多一點的工作,但我敢肯定,使用單一的順序讀取和移動工作給其他線程將是一個不錯的改進。歡呼的鏈接。 – 2013-04-23 09:09:00

1

首先,要從不同的偏移量開始同時讀取文件,您需要隨機訪問到文件,這意味着從任何位置讀取文件。 Java允許這與中的RandomAccessFile或java.in與SeekableByteChannel的java.nio中的:

Best Way to Write Bytes in the Middle of a File in Java

http://docs.oracle.com/javase/tutorial/essential/io/rafs.html

我認爲對於速度的原因,你會喜歡的java.nio。 Java NIO FileChannel versus FileOutputstream performance/usefulness

現在你知道如何從任何位置讀取,但你需要同時做到這一點。使用相同的文件訪問對象是不可能的,因爲它們保持文件中的位置。因此你需要和線程一樣多的文件訪問對象。既然你正在閱讀不寫,應該是好的。

現在你知道如何從許多不同的偏移量同時讀取同一個文件。

但考慮性能。儘管線程的數量只有一個磁盤驅動器和隨機讀取(多線程訪問同一個文件)的性能備受慢得多然後按順序讀取(一個線程讀取一個文件)。即使它突襲0或1 - 無所謂。連續閱讀總是快得多。所以在你的情況下,我建議你在一個線程中讀取文件,並向其他線程提供來自該讀線程的數據。要處理並插入

+0

乾杯維塔利和感謝的鏈接 – 2013-04-23 09:06:01