4

レポートの実行を変更して、並行して実行しようとしています。「シリアル モード」では実行テストに 30 秒かかり、同時実行モードを使用すると 27 秒かかります (シリアルでいくつかの手順を実行する必要があることを考慮してください。結果は問題ありません)。

私がまだ得ていないのは、この行です:

ExecutorService executor = Executors.newFixedThreadPool(4);

私のコンピューターは 2x2.6 Ghz クアッド コアで武装しており、newFixedThreadPool が高い (16) 場合、実行時間が減少すると予想されます。実際には、newFixedThreadPool を増やすほど、実行が遅くなります。これは疑問を投げかけます:私は何を間違っているのか、何を理解できていないのでしょうか?!?!

実行結果のスクリーンショットを 2 つ埋め込んでいます。

A. newSingleThreadExecuter - 23 秒で実行

B. newFixedThreadPool(4) - 43 秒で実行されます。

「Worker」を送信するたびに、system.out で currentTimeMillis を取得し、「fatched tkt」の結果は、データベースからデータを取得するのにかかるミリ秒です。(戦略 A では最大 3 ミリ秒、戦略 B では最大 7 ミリ秒かかります)。

    Stopper stopper = new Stopper();
    for (Long iNum : multimap.asMap().keySet())
    {
        List<Long> tickets = (List<Long>) multimap.get(iNum);
        for (Long ticketNumber : tickets)
        {
                pojoPks = getPkData(iNum);
                Callable<PojoTicket> worker = new MaxCommThread(ticketNumber, pojoPks);
                Future<PojoTicket> submit = executor.submit(worker);
                futures.add(submit);
        }
    }

    System.out.println("futurues: " +futures.size());
    for (Future<PojoTicket> future : futures)
    {
        try
        {
            PojoTicket pojoTicket = future.get();
            //do the rest here

        } catch (InterruptedException e)
        {
            System.out.println("---------------------->InterruptedException");
        } catch (ExecutionException e)
        {
            System.out.println("---------------------->ExecutionException");
        }
    }

    executor.shutdown();
    stopper.stop();

ここに画像の説明を入力

ここに画像の説明を入力

4

1 に答える 1

5

newFixedThreadPool を増やすほど、実行が遅くなります

一般に、ジョブにスレッドを追加しても速度が上がらない場合は、次の 2 つの理由のいずれかが原因である可能性があります。

  • 各ジョブは何らかのリソースで同期する必要があるため、すべてのジョブがロックの競合のために戦っており、独立して実行されていません。

  • ジョブには、実行する CPU 作業があまりありません。IO バウンド プロセスにスレッドを追加しても、IO チャネルが既に上限に達している可能性があるため、処理が速くなるわけではありません。

ただし、アプリケーションの実行速度が半分になると興味深い状況になります。この2つの組み合わせだとしか思えません。

試してみるべきことの 1 つは、1 つのスレッドから開始してから 2 を試すことです。実行速度が速くならない場合は、まずジョブ間で共有されているロックを確認してください。各ジョブによって変更されている並行コレクションまたはその他のオブジェクトは? ロックの数を減らすか、スレッドに一時情報を保存してから、一度ロックして中央オブジェクトを更新してください。

システム統計を見て、IO チャネルが使い果たされているかどうかを確認することもできます。ここで一般的な問題をディスクします。メモリ ディスクで実行できるかどうかを確認して、アプリケーションがより高速に実行されるかどうかを確認します。これは、IO バウンドであることを示す指標になります。

ExecutionException最後に、仕事が得られたときに sが発生する理由を調べます。これは他の問題の兆候である可能性がありますが、最初にこれを理解する必要があります。

于 2012-08-02T18:06:39.717 に答える