Fork/join and parallel streams question 106 of 180 mid
Why is forEach on a parallel stream dangerous, and what should you use?
- It is single threaded
- Correct: It runs unordered from many threads, so shared accumulation is a race; use
collect - It throws on a parallel stream
- It silently drops elements
forEach makes no ordering promise and calls your lambda from every worker thread at once. Adding to
an ArrayList from it corrupts the list; adding to a Collectors.toList result via a side effect is
the same bug with more steps.
List<String> out = new ArrayList<>();
stream.parallel().forEach(out::add); // race, lost elements, occasional exception
List<String> out = stream.parallel().collect(toList()); // correct and faster
collect is designed for this: each thread accumulates into its own container and the containers are
merged. forEachOrdered restores encounter order at the cost of the parallelism you asked for. And
even a synchronized list is the wrong fix, since every element then serialises on one lock.
Quiz yourself on Fork/join and parallel streams Suggest a correction