Warm-up

Count the threads

5 minintermediate210 yrs

One concept, guided. Near-impossible to fail.

What this teaches

  • A pool queues before it creates threads beyond corePoolSize
  • With an unbounded queue, maximumPoolSize is never reached
  • Executors.newFixedThreadPool gives you exactly that queue

Starter

Starter.javaOpen in playground
import java.util.concurrent.*;

/**
 * WARM-UP — 5 minutes. One concept. Hard to fail.
 *
 * A pool configured to grow from 1 thread to 10, given 50 slow tasks.
 *
 * TASKS
 *   1. Write down how many threads you expect. Actually write it.
 *   2. Run it.
 *   3. Change ONLY the queue — swap LinkedBlockingQueue for
 *      `new ArrayBlockingQueue<>(5)` — and run again. Nothing else changes.
 *   4. In a comment: state the order a ThreadPoolExecutor uses its three
 *      settings. The second step is the one everyone gets wrong.
 */
public class Starter {
    public static void main(String[] args) throws Exception {
        ThreadPoolExecutor pool = new ThreadPoolExecutor(
                1,                                  // corePoolSize
                10,                                 // maximumPoolSize
                60, TimeUnit.SECONDS,
                new LinkedBlockingQueue<>());       // (3) change only this line

        CountDownLatch release = new CountDownLatch(1);
        int rejected = 0;

        for (int i = 0; i < 50; i++) {
            try {
                pool.execute(() -> {
                    try {
                        release.await();
                    } catch (InterruptedException e) {
                        Thread.currentThread().interrupt();
                    }
                });
            } catch (RejectedExecutionException e) {
                rejected++;
            }
        }

        Thread.sleep(200);

        System.out.println("configured   : core=1 max=10, 50 tasks submitted");
        System.out.println("threads made : " + pool.getPoolSize());
        System.out.println("queued       : " + pool.getQueue().size());
        System.out.println("rejected     : " + rejected);

        release.countDown();
        pool.shutdown();
        pool.awaitTermination(5, TimeUnit.SECONDS);

        // Question to answer in a comment before you move on:
        // maximumPoolSize is 10 in both runs. In one of them it may as well
        // not be there. What has to be true before it means anything?
    }
}

Run it locally:

cd exercises/java/concurrency/executor-service/01-warmup
javac Starter.java -d /tmp/out && java -cp /tmp/out Starter

Done when

  • You predicted the thread count before running, and were wrong
  • Changing only the queue changes the answer, with no other edit
  • A comment states the order the three settings are used in

← Back to How do you size a thread pool, and what does an unbounded queue cost you?