The parallel streams promise

Java 8 Course · lesson 12 of 16 · 4 min read

Java 8 sold free parallelism. Here is when the promise holds and when it costs you.

Open this lesson in the learning hub

Key points

  • Adding .parallel() really does split the work across the common ForkJoinPool.
  • It pays off when the data is large, splitting is cheap, and the work per element is CPU-bound.
  • It loses when the source splits badly (LinkedList), the work is tiny, or you block on I/O.
  • The common pool is shared by the whole JVM - one blocking parallel stream stalls unrelated code.
  • Order-sensitive operations pay extra to preserve encounter order, which can erase the gain entirely.

Example

import java.util.*;
import java.util.stream.*;

public class Main {
    public static void main(String[] args) {
        List<Integer> data = IntStream.rangeClosed(1, 2_000_00).boxed().collect(Collectors.toList());

        long t1 = System.nanoTime();
        long seq = data.stream().mapToLong(Main::work).sum();
        long seqMs = (System.nanoTime() - t1) / 1_000_000;

        long t2 = System.nanoTime();
        long par = data.parallelStream().mapToLong(Main::work).sum();
        long parMs = (System.nanoTime() - t2) / 1_000_000;

        System.out.println("sequential : " + seq + "  (" + seqMs + " ms)");
        System.out.println("parallel   : " + par + "  (" + parMs + " ms)");
        System.out.println("same answer: " + (seq == par));
        System.out.println("cores      : " + Runtime.getRuntime().availableProcessors());
        System.out.println("(timings vary; on a small input parallel is often slower)");
    }

    static long work(int n) {
        return (long) Math.sqrt(n) + (n % 7);
    }
}

Parallel is a measurement, not a decision - if you have not timed it, leave it sequential.

This is a reading copy. The full lesson — with the visual explainer, the interactive lab and a Run button for the code — lives in the Java 8 Course course, and every lesson in it is listed on the Java 8 Course contents page.