Both invoke..()
and submit()
will execute their tasks immediately (assuming threads are available to run the tasks). The difference is that invoke...()
will wait for the tasks running in separate threads to finish before returning a result, whereas submit()
will return immediately, meaning the task it executed is still running in another thread.
In other words, the Future
objects returned from invokeAll()
are guaranteed to be in a state where Future.isDone() == true
. The Future
object returned from submit()
can be in a state where Future.isDone() == false
.
We can easily demonstrate the timing difference.
public static void main(String... args) throws InterruptedException {
Callable<String> c1 = () -> { System.out.println("Hello "); return "Hello "; };
Callable<String> c2 = () -> { System.out.println("World!"); return "World!"; };
List<Callable<String>> callables = List.of(c1, c2);
ExecutorService executor = Executors.newSingleThreadExecutor();
System.out.println("Begin invokeAll...");
List<Future<String>> allFutures = executor.invokeAll(callables);
System.out.println("End invokeAll.\n");
System.out.println("Begin submit...");
List<Future<String>> submittedFutures = callables.stream().map(executor::submit).collect(toList());
System.out.println("End submit.");
}
And the result is that the callables
print their Hello World message before the invokeAll()
method completes; but the callables
print Hello World after the submit()
method completes.
/*
Begin invokeAll...
Hello
World!
End invokeAll.
Begin submit...
End submit.
Hello
World!
*/
You can play around with this code in an IDE by adding some sleep()
time in c1
or c2
and watching as the terminal prints out. This should convince you that invoke...()
does indeed wait for something to happen, but submit()
does not.