Commit 0e8b360
committed
feat(streams): add ParallelStream demo comparing sequential vs parallel performance and pitfalls
What
- Implemented `ParallelStream.java` to showcase:
- Performance comparison between sequential stream and parallel stream when computing factorials for numbers 1–20,000.
- Example of cumulative sum using sequential stream.
- Demonstrated potential benefits (performance) and pitfalls (incorrect results with shared mutable state).
Why
- Developers often assume parallel streams are always faster.
- This demo shows:
- Parallelism improves throughput for CPU-heavy, independent tasks (factorials).
- But parallelism breaks correctness when using shared mutable state (cumulative sum).
- Encourages safe and deliberate use of parallel streams.
Logic
1. **Factorial calculation (CPU-intensive)**
- Generated a list of numbers 1–20,000 using `Stream.iterate()`.
- Sequential stream: `list.stream().map(ParallelStream::factorial)` measured execution time.
- Parallel stream: `list.parallelStream().map(ParallelStream::factorial)` measured execution time.
- Parallel execution leverages multiple threads, usually yielding better performance.
2. **Cumulative sum (stateful & order-sensitive)**
- Input: `[1, 2, 3, 4, 5]`
- Sequential stream with `AtomicInteger.addAndGet()` → produces correct cumulative sum `[1, 3, 6, 10, 15]`.
- If run in parallel, results are inconsistent because threads update the same mutable `AtomicInteger` concurrently in non-deterministic order.
- Highlights why shared mutable state is unsafe with parallel streams.
Best practices
- ✅ Use parallel streams for:
- CPU-intensive, independent, and stateless tasks.
- Large datasets where parallelism amortizes overhead.
- ❌ Avoid parallel streams for:
- Small datasets (thread overhead > benefit).
- Stateful, order-sensitive, or side-effect operations (like cumulative sum).
- Shared mutable data structures without synchronization.
Real-world applications
- ✅ Suitable: computing aggregates (factorials, sums, analytics), large log/event processing.
- ❌ Unsafe: ordered calculations (cumulative sums, dependent transformations), shared counters without care.
Notes
- Parallel streams internally use the ForkJoinPool (common pool).
- `parallelStream().sequential()` allows reverting back to sequential execution mid-pipeline.
- Streams are declarative, but correctness depends on respecting immutability and independence of operations.
Signed-off-by: https://github.com/Someshdiwan <[email protected]>1 parent cc0fdfb commit 0e8b360
File tree
1 file changed
+3
-2
lines changed- Java 8 Crash Course/Java 8 Streams/Parallel Streams/src
1 file changed
+3
-2
lines changedLines changed: 3 additions & 2 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
9 | 9 | | |
10 | 10 | | |
11 | 11 | | |
| 12 | + | |
12 | 13 | | |
13 | 14 | | |
14 | 15 | | |
| |||
17 | 18 | | |
18 | 19 | | |
19 | 20 | | |
20 | | - | |
| 21 | + | |
21 | 22 | | |
22 | 23 | | |
23 | 24 | | |
| |||
41 | 42 | | |
42 | 43 | | |
43 | 44 | | |
44 | | - | |
| 45 | + | |
0 commit comments