2013-04-23 29 views
5

これから少しずつ見ていますが、私はこの問題について少し混乱しています。私は入力ストリームを取得し、それを同時にセグメントで読み取ることができるようにしたい。セグメントは相互に作用しません。セグメントは、アップロードされたファイルからデータベースに挿入または更新される値だけです。セグメントサイズを設定して入力ストリームを同時に読み取ってから、新しいスレッドをスピンオフして変換と挿入/更新を処理する前にスキップすることは可能ですか?Java:InputStreamでの同時読み込み

本質的にファイルはIDのリスト(1行に1つのID)ですが、区切り記号を指定することができればそれが望ましいでしょう。いくつかのファイルは膨大になる可能性があるので、データを処理してセグメントに変換して、データベースに挿入/更新した後にJVMメモリを解放することができます。これは可能ですか?もし既にそうしているライブラリがあれば、そこにはありますか?事前に

乾杯と感謝、

アレクセイ・ブルー。

答えて

6

代わりに、チャンクを読み込んだ後、各チャンクをスレッドプールからワーカースレッドに渡す単一のリーダーを用意するのがよい方法です。これらがデータベースに挿入されることを考えれば、挿入物は入力を読むことと比較して遅い部分であり、読み取りのためには単一のスレッドで十分である。

以下は、System.inからワーカースレッドまで各行の処理を引き渡す例です。 1つのトランザクション内で多数の挿入を実行すると、1000行のグループを渡すほうが、この例のように1行を渡すよりも優れているはずです。

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

こんにちはEdは感謝しています^。^ 1000行をStringBufferに読み込んでこれをワーカースレッドに渡して処理し、データベースに挿入/更新すると良いアプローチになると思いますか? :) –

+0

1000行を 'List 'や 'String []'に読み込むのが最善でしょう。 'StringBuffer'にそれらを読み込むと、それは単一の文字列になり、個々の行をもう一度解析する必要があります。 –

1

あなたはInputStreamを同時に読むことはできません。そのため、契約では読み込み、リセット、マークが定義されています。つまり、ストリームは読み込まれた内容と読み出されなかった内容を内部で追跡しています。

ファイルを読んでいる場合は、複数のストリームを開くだけです。 skip()メソッドを使用すると、行の重複を避けるために他のスレッドのマーカーを先に移動できます。 BufferedReaderも読書line by lineを提供しているので、いくらか助けるかもしれません。

+0

ええ、バッファリングされたリーダー+スキップは、私が現在やっている方法です、もう少し作業が必要ですが、私は確かに単一のシーケンシャル読み取りと他のスレッドへの作業を移動することは良い改善になると確信しています。リンクのための乾杯。 –

1

まず、異なるオフセットから同時にファイルを読み取るには、ランダムアクセスが必要です。これは、ファイルを任意の位置から読み取ることを意味します。 Javaはjava.inやjava.nioのSeekableByteChannelでのRandomAccessFileでこれを可能にする:

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

ここでどのように読むかを知っていますが、これを同時に実行する必要があります。ファイル内の位置を保持するため、同じファイルアクセスオブジェクトでは不可能です。したがって、スレッドと同じ数のファイルアクセスオブジェクトが必要です。あなたが書いていないことを読んでいるので、それはOKであるべきです。

これで、同じファイルをさまざまなオフセットから同時に読み取る方法が分かりました。

しかし、パフォーマンスについて考えてみてください。スレッド数にもかかわらず、1つのディスクドライブとランダムな読み取り(多くのスレッドが同じファイルにアクセスします)のパフォーマンスは、順次読み取り(1つのスレッドが1つのファイルを読み込む)よりはるかに遅いです。たとえそれが0または1の襲撃であっても問題ではありません。シーケンシャルリーディングは常にずっと高速です。だからあなたの場合は、あるスレッドでファイルを読み、その読み込みスレッドからのデータを他のスレッドに提供することをお勧めします。

+0

乾杯、ヴィタリとリンクありがとう –

関連する問題