The 30 second answer
I avoid it on small data or cheap per-element work where split cost dominates, on poorly splittable sources like LinkedList, and whenever lambdas do blocking IO or touch shared mutable state. Order-sensitive ops get expensive in parallel, and on a busy Spring Boot server the common pool is already shared. Always measure first.
[Opinion, grounded in the docs]
- Small data / cheap per-element work: split and merge overhead dominates.
- Poorly splittable sources:
LinkedList,Stream.iterate, I/O-backed streams. Good sources:ArrayList, arrays,IntStream.range. - Blocking I/O or DB calls in lambdas: they occupy the shared common
ForkJoinPoolused JVM-wide (including other parallel streams and manyCompletableFutureasync defaults), starving other work. - Order-dependent ops (
findFirst,limit,forEachOrdered,sorted) on ordered streams are costly in parallel;unordered()can help. - Shared mutable state / side effects (for example
list.addinforEach) → race conditions. - Inside request-handling servers (for example a Spring Boot web app) where threads are already saturated.
Always measure (JMH) before enabling.
Sources:
Sources (0)
See inline citations in the answer above.