In a nutshell, parallel processing a stream refers to a process that consists of three steps:
- Splitting the elements of a stream into multiple chunks
- Processing each chunk in a separate thread
- Joining the results of processing in a single result
These three steps take place behind the scenes via the default ForkJoinPool method as we discussed in Chapter 10, Concurrency – Thread Pools, Callables, and Synchronizers and Chapter 11, Concurrency – Deep Dive.
As a rule of thumb, parallel processing can be applied only to stateless (the state of an element doesn't affect another element), non-interfering (the data source is not affected), and associative (the result is not affected by the order of operands) ...