以下のコードで示すように、CompletableFuture
を使用しています。しかし、すべての実行可能ファイルが終了するまで待つ方法については、2つの方法を見つけましたが、それらの違いとどちらがベストプラクティスであるかがわかりません。それらは次のとおりです。
コード:
this.growSeedFutureList = CompletableFuture.runAsync(new GrowSeedSERun(this.saliencyMat, this.seedXY, this.seedVal), this.growSeedExecutor);
this.growSeedFutureList = CompletableFuture.runAsync(new GrowSeedNWRun(this.saliencyMat, this.seedXY, this.seedVal), this.growSeedExecutor);
this.growSeedFutureList = CompletableFuture.runAsync(new GrowSeedNERun(this.saliencyMat, this.seedXY, this.seedVal), this.growSeedExecutor);
this.growSeedFutureList = CompletableFuture.runAsync(new GrowSeedSWRun(this.saliencyMat, this.seedXY, this.seedVal), this.growSeedExecutor);
すべての実行可能ファイルが終了するまで待機する最初のアプローチ:
this.growSeedExecutor.shutdown();
this.growSeedExecutor.awaitTermination(1, TimeUnit.DAYS);
すべての実行可能ファイルが終了するまで待機する2番目のアプローチ:
CompletableFuture.allOf(this.growSeedFutureList).join();
どれが推奨されるか教えてください。
両方の方法は、エグゼキュータ(growSeedExecutor)が特定のタスクにのみ使用される場合にのみ同等です。最初の方法は次のようになる可能性があります。別のタスクには並列化が必要であり、タスクごとに新しいエクゼキューターが作成されます。一部の開発者は、作成されたエグゼキューターの数が多すぎて、単一の共通エグゼキューターを使用することに決めましたが、すべてのエグゼキューターのシャットダウンを削除できませんでした...
したがって、2番目の方法(join())は、それほど複雑ではないため、より信頼性が高くなります。ただし、新しい未来はそれぞれ、growSeedFutureListに追加する必要があり、割り当てられません。
すべての先物を本当に待ちたい場合は、それぞれの先物でjoin()
を呼び出すだけです:
_growSeedFutureList.forEach(CompletableFuture::join);
_
allOf()
を使用することと比較した主な違いは、例外が完了したfutureに到達するとすぐに例外がスローされるのに対して、allOf().join()
バージョンはすべてのfutureの後のみ例外をスローすることです。完了した(例外的に、またはそうでない)。
もう1つの小さな違いは、これにより中間allOf
ステージが作成されないことです。そのようなステージは、すべてのフューチャーが完了するのを待つのではなく、すべてのフューチャーが完了した後に何かを非同期的に実行する場合に役立ちます。
反対側のエグゼキューターを使用したソリューションには、いくつかの欠点があります。
CompletableFuture
sでは機能しません。awaitTermination()
によって例外はスローされません。