では、一連のタスクを送信する方法が 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));
}