Lab 08: ForkJoinPool & Parallel Algorithms

Objective

Master the ForkJoinPool framework: RecursiveTask<T> for parallel computation (divide-and-conquer sum), RecursiveAction for parallel in-place mutation (bulk discount), work stealing, custom pool parallelism, and comparison with parallel streams.

Background

ForkJoinPool (Java 7+) implements a work-stealing algorithm — idle worker threads steal tasks from busy workers' queues. This maximises CPU utilisation for divide-and-conquer algorithms. RecursiveTask<T> returns a result; RecursiveAction performs a side-effect. The common pool (shared by parallel streams, CompletableFuture.supplyAsync) defaults to Runtime.availableProcessors()-1 threads.

Time

25 minutes

Prerequisites

  • Practitioner Lab 05 (Concurrency)

Tools

  • Docker: zchencow/innozverse-java:latest


Lab Instructions

Steps 1–8: RecursiveTask sum, RecursiveAction discount, work stealing, custom pool, parallel streams comparison, Capstone

💡 left.fork(); right.compute(); left.join() is the canonical ForkJoin pattern. fork() submits the left half to the pool asynchronously. Then the current thread computes the right half directly (saving a thread-switch). Finally join() awaits the left result. This maximises work per thread. Never call left.fork(); left.join() consecutively — that's just sequential.

📸 Verified Output:


Summary

API
Returns
Use for

RecursiveTask<T>

T

Divide-and-conquer with result

RecursiveAction

void

Parallel side-effects

task.fork()

Submit sub-task to pool

task.join()

T

Await sub-task result

pool.invoke(task)

T

Submit + await from outside pool

invokeAll(t1, t2)

Fork both, join both

Further Reading

Last updated