liveBook · Manning

Thread pool

As explained in Functional Programming in Scala, Second Edition

A thread pool is a managed set of reusable worker threads that execute submitted tasks, optionally with a fixed maximum size.

A thread pool is a managed set of worker threads that executes submitted tasks. A fixed-size pool imposes a maximum number of workers, making resource availability part of a parallel program’s behavior. section 7.3.3

The central hazard appears when a task running in the pool submits another task and blocks on its Future. With one worker, the outer task occupies the only thread while waiting for the inner task, which cannot start. section 7.3.3

Trace a suspected deadlock by asking:

  • How many workers can the ExecutorService run simultaneously? section 7.3.3
  • Does a running task submit another task before it completes? section 7.3.3
  • Does the running task wait on the submitted task’s Future? section 7.3.3
  • Are all workers blocked while another logical task waits to run? section 7.9

Nested fork with one worker

With Executors.newFixedThreadPool(1), running a computation such as fork(a) can deadlock when fork submits a Callable that evaluates a(es).get. The sole worker runs the outer Callable, waits for the inner Callable, and leaves no worker available for that inner computation. section 7.3.3

val a = lazyUnit(42 + 1)
val es = Executors.newFixedThreadPool(1)
println(Par.equal(es)(a, fork(a)))

Run the equality check with a one-worker pool to observe the interaction between fork, ExecutorService capacity, and blocking evaluation. section 7.3.3

How Functional Programming in Scala, Second Edition covers it

How deep it goes
Explains single-thread deadlock step by step and generalizes it to any fixed-size pool, without presenting a repair.
Examples
Uses a one-worker Executors.newFixedThreadPool example and the nested pattern fork(fork(fork(x))).
What it assumes
Assumes ExecutorService, Future, fork, and Par; does not teach these abstractions from zero.
What you can do after
Diagnose/debug with fixed-size thread pools by tracing submitted tasks, blocked Futures, and available workers.
How it connects
Connects thread pools to ExecutorService, Future, fork, parMap, parallel computation, and deadlock.

Also explained in

Compare how 10 books explain thread pool →

Related concepts

This explainer was generated by Manning's knowledge graph from the text of Functional Programming in Scala, Second Edition. The section links point to the parts of the book it draws on.