Warm-up

Find out whose threads you are using

10 minintermediate210 yrs

One concept, guided. Near-impossible to fail.

What this teaches

  • parallelStream submits to one JVM-wide common ForkJoinPool
  • The calling thread joins the work, so it is not asynchronous
  • Parallelism is cores minus one, decided by the machine and not by you
  • A parallel stream inside your own ForkJoinPool task uses that pool instead

Starter

Starter.java
import java.util.*;
import java.util.concurrent.*;
import java.util.stream.*;

/**
 * Warm-up: whose threads are these?
 *
 * parallelStream() does not create threads. Finding out which threads it does
 * use, by printing their names, answers most of this topic on its own.
 */
public class Starter {

    public static void main(String[] args) throws Exception {

        // TODO 1: predict the thread names before running. Then look at the
        // prefix — it names the pool, and the pool is the whole point.
        Set<String> threads = ConcurrentHashMap.newKeySet();
        IntStream.range(0, 10_000).parallel()
            .forEach(i -> threads.add(Thread.currentThread().getName()));

        System.out.println("distinct threads : " + threads.size());
        System.out.println("names            : " + new TreeSet<>(threads));

        // TODO 2: one of those names is not a worker. Which, and what does its
        // presence tell you about whether parallelStream is asynchronous?

        // TODO 3: print ForkJoinPool.getCommonPoolParallelism() and
        // Runtime.getRuntime().availableProcessors(). State the relationship,
        // then say what happens in a container limited to one core.

        // TODO 4: run two parallel streams from two different threads at the
        // same time and collect the names from both. Do they share workers?
        // That answer is the reason this entry exists.

        // TODO 5: now run the same stream inside your own pool:
        //
        //     ForkJoinPool mine = new ForkJoinPool(2);
        //     Set<String> names = mine.submit(() -> ...).get();
        //
        // The names change. Note that you did not pass the pool to the stream
        // — say where the stream found it, and why there is no overload that
        // takes one.

        // TODO 6: in one sentence, explain to a colleague why adding
        // .parallelStream() to a slow remote call can make an unrelated
        // endpoint time out.
    }
}

Run it locally:

cd exercises/java/java8/parallel-stream-pitfalls/01-warmup
javac Starter.java -d /tmp/out && java -cp /tmp/out Starter

Done when

  • You printed the thread names and identified the pool by name
  • You showed the calling thread doing work
  • You ran the same stream inside your own pool and saw the names change
  • You can say why a slow task here affects unrelated code in the same JVM

← Back to When is parallelStream() a mistake?