45

ExecutorCompletionServiceを使用すると、一連のタスクを として送信し、としてCallable相互作用する結果を取得できます。 CompletionServicequeue

しかし、 of のタスクを受け入れるinvokeAllofもあり、結果を取得するために のリストを取得します。 ExecutorServiceCollectionFuture

私が知る限り、どちらを使用してもメリットはありません (ただし、へのタスクに必要なをfor使用したループを回避します)。本質的には、わずかな違いを除いて同じ考え方です。 invokeAllsubmitCompletionService

では、一連のタスクを送信する方法が 2 つあるのはなぜでしょうか。パフォーマンスに関しては同等であると私は正しいですか?どちらかが適している場合はありますか?思いつきません。

4

4 に答える 4

19

では、一連のタスクを送信する方法が 2 つあるのはなぜでしょうか? パフォーマンスに関しては同等であると私は正しいですか?どちらかが適している場合はありますか?思いつきません。

を使用すると、ジョブが完了しExecutorCompletionServiceたときにすぐに通知を受け取ることができます。比較すると、のコレクションを返す前に、すべてのジョブが完了するのを待ちます。これは、(たとえば) 1 つのジョブを除くすべてのジョブが 10 分で完了し、1 つのジョブに 30 分かかる場合、30 分間結果が得られないことを意味します。ExecutorService.invokeAll(...)Future

// this waits until _all_ of the jobs complete
List<Future<Object>> futures = threadPool.invokeAll(...);

代わりに、 を使用するExecutorCompletionServiceと、それぞれのジョブが完了するとすぐにジョブを取得できるため、(たとえば) ジョブを送信して別のスレッド プールに処理したり、結果をすぐにログに記録したりできます。

ExecutorService threadPool = Executors.newFixedThreadPool(2);
ExecutorCompletionService<Result> compService
      = new ExecutorCompletionService<Result>(threadPool);
for (MyJob job : jobs) {
    compService.submit(job);
}
// shutdown the pool but the jobs submitted continue to run
threadPool.shutdown();
while (true) {
    Future<Result> future;
    // if pool has terminated (all jobs finished after shutdown) then poll() else take()
    if (threadPool.isTerminated()) {
        future = compService.poll();
        if (future == null) {
            break;
        }
    } else {
        // the take() blocks until any of the jobs complete
        // this joins with the jobs in the order they _finish_
        future = compService.take();
    }
    // this get() won't block
    Result result = future.get();
    // you can then put the result in some other thread pool or something
    // to immediately start processing it
    someOtherThreadPool.submit(new SomeNewJob(result));
}
于 2012-08-08T21:00:39.697 に答える
1

結果の順序のみを考慮して比較する:

CompletionService送信されたジョブが終了するたびに使用すると、結果がキューにプッシュされます (完了順序)。その後、送信されたジョブと返された結果の順序が同じではなくなります。したがって、タスクが実行される順序が気になる場合は、CompletionService

AsinvokeAllは、タスクを表す Future のリストを、指定されたタスク リストの反復子によって生成されたのと同じ順序で返します。各タスクは完了しています。

于 2013-01-14T19:49:10.057 に答える