I have a list of heavy tasks that should be run in parallel. I like the java Stream API and don't want to touch Executors directly, for that reason I've written the following code:
Set<Runnable> tasks = Set.of(heavyTask(),…);
tasks.parallelStream().forEach(Runnable::run);
Quite often (not always!) my concurrency tests fails during “heavy task” execution. OK, probably it's a race condition. I've rewritten the code using Executors directly:
try {
Set<Callable<Object>> tasks = Set.of(heavyTask(),…);
Executors.newFixedThreadPool(4)
.invokeAll(tasks).forEach(future->{
try {
future.get();
} catch (InterruptedException | ExecutionException ignore) {
}
});
} catch (InterruptedException ignore) {
}
The problem with heavy tasks is gone. I'm really confused. I thought that parallelStream() uses Executors under the hood and it's almost the same. Is there any difference between .parallelStream() and ExecutorService? Or maybe forEach isn't correct termination operation in the first code example?