3

ExecutorService と ArrayBlockingQueue を使用して、プロデューサーとコンシューマーの設計に関する私の理解が正しいかどうかを知りたいです。この設計を実装するにはさまざまな方法があることは理解していますが、最終的には問題自体に依存すると思います。

私が直面しなければならなかった問題は次のとおりです。大きなファイル (6 GB) から読み取る 1 つのプロデューサーがいます。行ごとに読み取り、すべての行をオブジェクトに変換します。オブジェクトを ArrayBlockingQueue に配置します。

コンシューマー (少数) は ArrayBlockingQueue からオブジェクトを取得し、これをデータベースに永続化します。

さて、明らかに生産者は消費者よりもはるかに高速です。各行をオブジェクトに変換するのに数秒かかりますが、消費者にとってはより長い時間がかかります。

したがって...これを行うことでこのプロセスをスピードアップしたい場合: 2 つのクラス化された「ProducerThread」と「ConsumerThread」を作成し、それらは ArrayBlockingQueue を共有します。2 つの間で調整するスレッドは次のようになります。

@Override
public void run()
{
    try{

        ArrayBlockingQueue<Ticket> queue = new ArrayBlockingQueue<Ticket>(40);
        ExecutorService threadPool = Executors.newFixedThreadPool(8);

        threadPool.execute(new SaleConsumerThread("NEW YORK", queue)); 
        threadPool.execute(new SaleConsumerThread("PARIS", queue));
        threadPool.execute(new SaleConsumerThread("TEL AVIV", queue));
        threadPool.execute(new SaleConsumerThread("HONG KONG", queue));
        threadPool.execute(new SaleConsumerThread("LONDON", queue));
        threadPool.execute(new SaleConsumerThread("BERLIN", queue));
        threadPool.execute(new SaleConsumerThread("AMSTERDAM", queue));

        Future producerStatus = threadPool.submit(new SaleProducerThread(progressBar, file, queue)); 
        producerStatus.get(); 
        threadPool.shutdown();   

    }catch(Exception exp)
    {
        exp.printStackTrace();
    }
}

私の質問は次のとおりです。

  1. 上記の設計は実際に各スレッドを同時に使用しますか? 私のコンピューターは 2.4GHz クアッドコア 2 台です。

  2. Future と .get() が何のためにあるのかわかりませんか?

ちなみに、結果は高速です (最初のバージョンはシーケンシャルで、3 時間かかったと考えてください)。今では 40 分ほどかかります (ただし、改善の余地があるかもしれません)。

ポインタをありがとう

4

2 に答える 2

2

IO の待機に費やされた時間と CPU で費やされた時間を調べます。主なボトルネックはデータベースだと思います。インポートをより効率的にする方法を検討する必要があります。これによりスループットが向上する可能性があるため、更新をバッチ処理してみてください。

于 2012-05-01T07:35:26.120 に答える
1

答え:

  1. 「各スレッドを同時に使用する」という意味がわかりません。しかし、確かにすべてのスレッドが同時に実行できます。パフォーマンスは、スレッドの数とデータの分割方法によって異なります。より良い結果を得るためにスレッドの数を試すことができます。また、都市ごとにスレッドを割り当てる代わりに、レコード番号を使用して、各スレッドをレコード番号のモジュラスに割り当てることができます。10 個のスレッドがあり、レコード 1、11、21 などはスレッド 1 に、2、22 などはスレッド 2 に移動するとします。このようにして、スレッドごとに同じ数のトランザクションを取得できるため、完了するまでスレッドを最大限に活用できます。
  2. これFutureは、イベントが完了したときにコードをブロックできるようにするためです。この場合get、メソッドは の結果を返しますSaleProducerThread
于 2012-05-01T05:15:53.773 に答える