1

ドキュメントのキュー (基本的には、入力ディレクトリにあるすべてのドキュメント) を処理するアプリケーションがあります。ドキュメントは 1 つずつ読み込まれ、処理されます。1 つのドキュメントを処理した結果は、他のドキュメントを処理した結果から完全に独立しているため、このアプリケーションは明らかにスレッド化の候補です。問題は、仕事をどのように分担するかです。

作業を分割する 1 つの明白な方法は、キュー内のドキュメントの数を数え、使用可能なプロセッサの数で割って、それに応じて作業を分割することです (たとえば、キュ​​ーに 100 個のドキュメントがあり、4 つの使用可能なプロセッサがある場合、4 つのスレッドを作成し、キューから各スレッドに 25 個のドキュメントをフィードします)。

ただし、同僚は、キュー内のドキュメントごとにスレッドを生成し、Java JVM にそれを整理させることができると提案しています。これがどのように機能するのかわかりません。2 番目の方法がよりクリーンなコードになることはわかりますが、最初の方法と同じくらい効率的 (またはさらに効率的) ですか?

任意の考えをいただければ幸いです。

エリオット

4

4 に答える 4

7

ドキュメントのキューを処理するアプリケーションがあります...どのように作業を分割しますか?

ExecutorService優れたクラスを使用する必要があります。次のようなものが機能します。各ファイルをスレッドプールに送信すると、それらは 10 個の作業スレッドによって処理されます。

 // create a pool with 10 threads
 ExecutorService threadPool = Executors.newFixedThreadPool(10);
 for (String file : files) {
     threadPool.submit(new MyFileProcessor(file));
 }
 // shutdown the pool once you've submitted your last job
 threadPool.shutdown();
 ...
 public class MyFileProcessor implements Runnable {
     private String file;
     public MyFileProcessor(String file) {
        this.file = file;
     }
     public run() {
        // process the file
     }
 }
于 2012-05-22T23:01:21.790 に答える
3

一般に、スレッド間で作業を分割するには 3 つの方法があります。

まず、静的パーティショニング。ここで、ドキュメントを静的にカウントして分割します (つまり、各ドキュメントの処理にかかる時間を考慮しません)。このアプローチは非常に効率的です (多くの場合、コーディングも簡単です) が、ドキュメントの処理にかかる時間が異なる場合、パフォーマンスが低下する可能性があります。1 つのスレッドがすべての長いドキュメントで誤ってスタックする可能性があります。これは、そのスレッドが最も長く実行され、並列処理が制限されることを意味します。

第二に、動的パーティショニング (あなたはこれについて言及していません)。一定数のスレッドを生成し、各スレッドが単純なループで動作するようにします。

While not done:
  Dequeue a document
  Process document

このようにして、負荷の不均衡を回避します。各ドキュメントの処理後にキューにアクセスするオーバーヘッドが発生しますが、各ドキュメントの処理がキュー アクセスよりも大幅に長い限り、無視できます (したがって、そうすべきだと思います)。

3 番目に、JVM に作業スケジューリングを任せます。これは、N 個のスレッドにまたがって、それらを戦わせる場所です。このアプローチはかなり単純ですが、欠点は、JVM のスレッド スケジューリングに大きく依存することであり、JVM がうまく機能しない場合は非常に遅くなる可能性があります。互いにスラッシュするスレッドが多すぎると、非常に遅くなる可能性があります。JVMがそれよりも優れていることを願っているので、試してみる価値があるかもしれません.

お役に立てれば。

于 2012-05-22T23:09:06.387 に答える
2

ドキュメントごとにスレッドを生成するのではなく、プロセッサと同じ数のスレッドを持つスレッドプールで Runnable タスクをスケジュールします。

于 2012-05-22T23:01:04.833 に答える
2

そのようにドキュメントを分割する必要はありません。一定数のワーカー スレッドを作成する (つまり、 を使用して 2 つのワーカー スレッドを作成するExecutors.newFixedThreadPool(2)) だけで、それぞれが一度に 1 つのドキュメントしか処理できません。1 つのドキュメントの処理が終了すると、共有リストから新しいドキュメントを取得します。

于 2012-05-22T23:01:52.587 に答える