Backend Development 10 min read

Ways to Create Thread Pools in JDK 1.8

This article introduces the various thread pool creation methods available in JDK 1.8—including fixed, cached, scheduled, single, single‑scheduled, and work‑stealing executors—explains their characteristics, provides sample Java code for each, and shows typical execution results.

Selected Java Interview Questions
Selected Java Interview Questions
Selected Java Interview Questions
Ways to Create Thread Pools in JDK 1.8

JDK 1.8 provides several factory methods in java.util.concurrent.Executors to create different types of thread pools.

Fixed thread pool (newFixedThreadPool) creates a pool with a fixed number of threads; new tasks are queued when all threads are busy, and terminated threads are replaced.

public class TestThreadPool {
    // Fixed thread pool with 3 threads
    static ExecutorService fixedExecutor = Executors.newFixedThreadPool(3);

    public static void main(String[] args) {
        testFixedExecutor();
    }

    private static void testFixedExecutor() {
        for (int i = 0; i < 6; i++) {
            final int index = i;
            fixedExecutor.execute(new Runnable() {
                public void run() {
                    try {
                        Thread.sleep(3000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println(Thread.currentThread().getName() + " index:" + index);
                }
            });
        }
        try {
            Thread.sleep(4000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("4秒后...");
        fixedExecutor.shutdown();
    }
}

Typical output shows the first three tasks running concurrently, followed by the remaining tasks after the earlier ones finish.

Cached thread pool (newCachedThreadPool) creates threads as needed and reuses idle ones; there is no upper bound on the number of threads.

public class TestThreadPool {
    // Cached thread pool
    static ExecutorService cachedExecutor = Executors.newCachedThreadPool();

    public static void main(String[] args) {
        testCachedExecutor();
    }

    private static void testCachedExecutor() {
        for (int i = 0; i < 6; i++) {
            final int index = i;
            cachedExecutor.execute(new Runnable() {
                public void run() {
                    try {
                        Thread.sleep(3000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println(Thread.currentThread().getName() + " index:" + index);
                }
            });
        }
        try {
            Thread.sleep(4000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("4秒后...");
        cachedExecutor.shutdown();
    }
}

Output demonstrates that threads are created on demand and may finish in any order.

Scheduled thread pool (newScheduledThreadPool) supports periodic or delayed execution of tasks.

public class TestThreadPool {
    static ScheduledExecutorService scheduledExecutor = Executors.newScheduledThreadPool(3);

    public static void main(String[] args) {
        testScheduledExecutor();
    }

    private static void testScheduledExecutor() {
        for (int i = 0; i < 3; i++) {
            final int index = i;
            scheduledExecutor.scheduleWithFixedDelay(new Runnable() {
                public void run() {
                    System.out.println(Thread.currentThread().getName() + " index:" + index);
                }
            }, 0, 3, TimeUnit.SECONDS);
        }
        try {
            Thread.sleep(4000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("4秒后...");
        scheduledExecutor.shutdown();
    }
}

Each task prints its index every three seconds.

Single‑thread executor (newSingleThreadExecutor) guarantees sequential execution of tasks in the order they are submitted.

public class TestThreadPool {
    static ExecutorService singleExecutor = Executors.newSingleThreadExecutor();

    public static void main(String[] args) {
        testSingleExecutor();
    }

    private static void testSingleExecutor() {
        for (int i = 0; i < 3; i++) {
            final int index = i;
            singleExecutor.execute(new Runnable() {
                public void run() {
                    try {
                        Thread.sleep(3000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println(Thread.currentThread().getName() + " index:" + index);
                }
            });
        }
        try {
            Thread.sleep(4000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("4秒后...");
        singleExecutor.shutdown();
    }
}

All tasks run on the same thread, preserving order.

Single‑thread scheduled executor (newSingleThreadScheduledExecutor) combines single‑threaded execution with periodic scheduling.

public class TestThreadPool {
    static ScheduledExecutorService singleScheduledExecutor = Executors.newSingleThreadScheduledExecutor();

    public static void main(String[] args) {
        testSingleScheduledExecutor();
    }

    private static void testSingleScheduledExecutor() {
        for (int i = 0; i < 3; i++) {
            final int index = i;
            singleScheduledExecutor.scheduleAtFixedRate(new Runnable() {
                public void run() {
                    System.out.println(Thread.currentThread().getName() + " index:" + index);
                }
            }, 0, 3, TimeUnit.SECONDS);
        }
        try {
            Thread.sleep(4000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("4秒后...");
        singleScheduledExecutor.shutdown();
    }
}

Only one thread executes the periodic tasks.

Work‑stealing pool (newWorkStealingPool) creates a ForkJoinPool that dynamically balances work among threads; task order is not guaranteed.

public class TestThreadPool {
    static ExecutorService workStealingExecutor = Executors.newWorkStealingPool();

    public static void main(String[] args) {
        testWorkStealingExecutor();
    }

    private static void testWorkStealingExecutor() {
        for (int i = 0; i < 10; i++) {
            final int index = i;
            workStealingExecutor.execute(new Runnable() {
                public void run() {
                    try {
                        Thread.sleep(3000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println(Thread.currentThread().getName() + " index:" + index);
                }
            });
        }
        try {
            Thread.sleep(4000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("4秒后...");
        // workStealingExecutor.shutdown(); // usually omitted because the pool shuts down when the main thread exits
    }
}

Output shows tasks being processed by different worker threads, and the last submitted tasks may not appear before the main thread finishes.

JavaConcurrencythreadpoolmultithreadingJDK8ExecutorService
Selected Java Interview Questions
Written by

Selected Java Interview Questions

A professional Java tech channel sharing common knowledge to help developers fill gaps. Follow us!

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.