web-dev-qa-db-ja.com

春のマルチスレッド

私は春のマルチスレッドに乗り込もうとしていますが、いくつか質問があります。

ThreadRatingクラスに実行可能なメソッドがあります。今、私はそれを使用する最良の方法についてはわかりません。

オプション1見つかりました:

_private void updateRating() {
        ExecutorService executor = Executors.newFixedThreadPool(10);

    for (int i = 0; i < 10; i++) { // test
        // thread part
        Runnable worker = new ThreadRating(path, i, products.get(i), dao, fileHandler);
        executor.execute(worker);
    }
    executor.shutdown();
    try {
        executor.awaitTermination(Long.MAX_VALUE, TimeUnit.NANOSECONDS);
    } catch (InterruptedException e) {
        log.error("There was an error when ending threads");
        System.exit(1);
    }
    System.out.println("Finished all threads");
}
_

これは正常に動作しているようです。 forループの後、スレッドが終了して終了するまで待機します。

私が試した2番目のオプション

_private TaskExecutor taskExecutor;

public UpdateBO(TaskExecutor taskExecutor) {
    this.taskExecutor = taskExecutor;
}

private void updateRating() {
        for (int i = 0; i < 10; i++) { // test
            Runnable worker = new ThreadRating(path, i, products.get(i), dao, fileHandler);
            taskExecutor.execute(worker);
        }
    // wait for threads to be finished before you go any further ??
        }
_

そして私が持っているxmlファイルで

_<beans:bean id="taskExecutor"
    class="org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor">
    <beans:property name="corePoolSize" value="5" />
    <beans:property name="maxPoolSize" value="10" />
    <beans:property name="queueCapacity" value="25" />
    <beans:property name="waitForTasksToCompleteOnShutdown" value="true" />
</beans:bean>

<beans:bean id="updateBO" class="UpdateBO">
    <beans:constructor-arg ref="taskExecutor" />
</beans:bean>
_

そしてここに私の質問があります:

  1. これら2つのオプションに違いはありますか?速度、メモリ、リークの可能性?それとも同じように書かれただけですか?
  2. Webサービスを使用するときにプールをシャットダウンする必要がありますか? 2番目のオプションでは必須ではないことは知っていますが、Webサービスを使用する場合も同じですか?
  3. 2番目のオプションを使用する場合-すべてのジョブが完了するまで待機するように指示するにはどうすればよいですか?最初のオプションでは、プールをシャットダウンして終了するのを待ちます。ただし、2番目のオプションでは、タスクが完了する前にコード要求が終了します。
  4. executor.execute(worker);-明確にするためです。これは実際には新しいスレッドを作成していませんが、タスクをキューに追加し、キューがいっぱいの場合は、空きスペースができるまでコードのこの行で待機しますか?

理解してくれてありがとう。

11
Elis.jane
  1. 主な違い:オプション1)では、すべてのupdateRating()呼び出しで新しいエグゼキューターを作成します。オプション2)では、エグゼキューターをデプロイ時に一度作成し、同じ単一のエグゼキューターに新しいジョブをフィードします。 2番目のアプローチははるかに優れています。

  2. エグゼキューターをシャットダウンする必要があるのはなぜですか? 新しいエグゼキューターを作成し、タスクが処理されるまで待つためにそれらをシャットダウンすることはアンチパターンですエグゼキュータは、システムリソースを制御するために作成され、そのように扱われる必要があることに注意してください。 (たとえば、50接続のDB接続プールがある場合-DBアクセスを提供するには、50スレッドのエグゼキューターを作成します-接続制限を超えないようにします。または、サーバーに24コアがあり、可能な限り最良の方法で作業を並列化する必要があります) 。

    また、コメントで述べたように、一部の環境(アプリサーバーなど)では、executorをシャットダウンする権限がない場合があります。そのような試みはSecurityExceptionを生成します。

  3. ワーカーがジョブを完了するまで待機する必要がある場合は、すべてのジョブをCallableではなくRunnableでラップし、メインスレッドから対応するfuture.get()を呼び出すと、ジョブまでブロックされます終了します。タイムアウトがサポートされています。

  4. 絶対的に正しい。スレッドは、最適なタイミングであると考えられる場合、executor自体によって作成および破棄されます。 jvisualvmを使用してアプリを監視し、どのように発生するかを確認してください。

6
Alex Salauyou

1.)オプション1は、executorサービスをローカルで定義し、使用するたびに閉じるため、正しく実装されていません。これは、スレッドプールを作成する目的に反します。スレッドプールはグローバルオブジェクトである必要があるため、オプション2が適しています。

2.)Webサービスを呼び出すときに、executorサービスをシャットダウンする必要はありません。 Webサービスが応答しない場合、呼び出しは最終的にタイムアウトし、スレッドは実行を完了します。 executorサービスをシャットダウンすると、次の呼び出しで使用できなくなります。

3.)スレッドが終了した後に何らかの通知が必要な場合は、代わりに CallableFutures と組み合わせて使用​​する必要があります。

4.)エグゼキューターサービスには最大10個のスレッドが割り当てられており、それらを超えるスレッドは生成されません。それらのすべてがビジーの場合、これらのスレッドの1つが使用可能になるまで、タスクはアイドル状態になります。

3
Fritz Duchardt