Language
日本語
English

Caution

JavaScript is disabled in your browser.
This site uses JavaScript for features such as search.
For the best experience, please enable JavaScript before browsing this site.

Java Dictionary

  1. Home
  2. Java Dictionary
  3. ExecutorService / Executors.newFixedThreadPool()

ExecutorService / Executors.newFixedThreadPool()

Since: Java 5(2004)

A mechanism for efficiently executing multiple tasks in parallel using a thread pool (available since Java 5). Because it automatically manages thread creation, reuse, and termination, it is safer and more performant than using Thread directly.

Syntax

import java.util.concurrent.*;

// Creates a fixed-size thread pool.
ExecutorService exec = Executors.newFixedThreadPool(numThreads);

// Creates an Executor backed by a single thread.
ExecutorService exec = Executors.newSingleThreadExecutor();

// Creates a pool that grows and shrinks as needed.
ExecutorService exec = Executors.newCachedThreadPool();

// Submits a Runnable task (no return value).
exec.execute(Runnable task);

// Submits a Callable task and returns a Future (with return value).
Future<T> future = exec.submit(Callable<T> task);
T result = future.get(); // Blocks until the result is available.

// Shuts down the ExecutorService (required).
exec.shutdown();
exec.shutdownNow(); // Forcibly stops all running tasks.

Main Methods

MethodDescription
Executors.newFixedThreadPool(n)Creates a fixed-size pool with n threads.
Executors.newSingleThreadExecutor()Queues and executes tasks sequentially on a single thread.
Executors.newCachedThreadPool()Creates and reuses threads as needed. Well-suited for short-lived tasks.
execute(Runnable)Executes a task asynchronously. Returns no value.
submit(Callable<T>)Executes a task asynchronously and returns the result as a Future<T>.
future.get()Blocks and waits until the task's result is available.
shutdown()Stops accepting new tasks and waits for existing tasks to complete before terminating.
shutdownNow()Interrupts running tasks and shuts down immediately.
awaitTermination(timeout, unit)Waits for termination up to the specified timeout.

Sample Code

ExecutorServiceExample.java
import java.util.concurrent.*;

class ExecutorServiceExample {
    public static void main(String[] args) throws InterruptedException {
        // Runs 5 tasks concurrently using a pool of 3 threads.
        ExecutorService exec = Executors.newFixedThreadPool(3);

        for (int i = 1; i <= 5; i++) {
            final int taskId = i;
            exec.execute(() -> {
                System.out.println("Task " + taskId + " running on: " + Thread.currentThread().getName());
                try { Thread.sleep(500); } catch (InterruptedException e) { Thread.currentThread().interrupt(); }
                System.out.println("Task " + taskId + " completed.");
            });
        }

        // Stops accepting new tasks and waits for remaining tasks to finish.
        exec.shutdown();

        // Uses submit() to run tasks that return a value.
        ExecutorService exec2 = Executors.newFixedThreadPool(2);
        Future<Integer> future1 = exec2.submit(() -> { Thread.sleep(200); return 10 + 20; });
        Future<Integer> future2 = exec2.submit(() -> { Thread.sleep(100); return 30 + 40; });

        try {
            System.out.println("Result 1: " + future1.get());
            System.out.println("Result 2: " + future2.get());
        } catch (InterruptedException | ExecutionException e) {
            e.printStackTrace();
        } finally {
            exec2.shutdown();
        }
    }
}

The command looks like this:

javac ExecutorServiceExample.java
java ExecutorServiceExample
# * Thread execution order may vary by environment
Task 1 running on: pool-1-thread-1
Task 2 running on: pool-1-thread-2
Task 3 running on: pool-1-thread-3
Task 1 completed.
Task 4 running on: pool-1-thread-1
Task 2 completed.
Task 5 running on: pool-1-thread-2
Task 3 completed.
Task 4 completed.
Task 5 completed.
Result 1: 30
Result 2: 70

Note: Thread execution order may vary depending on the runtime environment.

Common Mistakes

Common Mistake 1: Forgetting to call shutdown() leaves the program running indefinitely

Son Goku submitted tasks but forgot to call shutdown(), so the thread pool remained alive and the program never terminated.

ExecutorNoShutdownNg.java
import java.util.concurrent.*;

class ExecutorNoShutdownNg {
    public static void main(String[] args) {
        ExecutorService exec = Executors.newFixedThreadPool(2);
        exec.execute(() -> System.out.println("Task completed."));
    }
}

The command looks like this:

javac ExecutorNoShutdownNg.java
java ExecutorNoShutdownNg
Task completed.
(the program hangs and never exits)

As Vegeta fixed it, calling shutdown() inside a try-finally block ensures the program exits normally.

ExecutorNoShutdownOk.java
import java.util.concurrent.*;

class ExecutorNoShutdownOk {
    public static void main(String[] args) {
        ExecutorService exec = Executors.newFixedThreadPool(2);
        try {
            exec.execute(() -> System.out.println("Task completed."));
        } finally {
            exec.shutdown();
        }
    }
}

The command looks like this:

javac ExecutorNoShutdownOk.java
java ExecutorNoShutdownOk
Task completed.

Common Mistake 2: Exceptions thrown by submit() tasks go unnoticed until Future.get() is called

Piccolo submitted a task using submit() but never called Future.get(), so the exception thrown inside the task was silently swallowed.

ExecutorExceptionNg.java
import java.util.concurrent.*;

class ExecutorExceptionNg {
    public static void main(String[] args) {
        ExecutorService exec = Executors.newSingleThreadExecutor();
        Future future = exec.submit(() -> {
            throw new RuntimeException("Something went wrong!");
        });
        exec.shutdown();
        System.out.println("Done.");
    }
}

The command looks like this:

javac ExecutorExceptionNg.java
java ExecutorExceptionNg
Done.

As Son Gohan fixed it, calling Future.get() and catching ExecutionException lets you detect any exception thrown inside the task.

ExecutorExceptionOk.java
import java.util.concurrent.*;

class ExecutorExceptionOk {
    public static void main(String[] args) {
        ExecutorService exec = Executors.newSingleThreadExecutor();
        Future future = exec.submit(() -> {
            throw new RuntimeException("Something went wrong!");
        });
        try {
            future.get();
        } catch (ExecutionException e) {
            System.out.println("Task threw an exception: " + e.getCause().getMessage());
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        } finally {
            exec.shutdown();
        }
    }
}

The command looks like this:

javac ExecutorExceptionOk.java
java ExecutorExceptionOk
Task threw an exception: Something went wrong!

Notes

Using a thread pool reduces the overhead of creating threads and improves application throughput. For Executors.newFixedThreadPool(), it is common to set the thread count to match the number of CPU cores. For I/O-bound workloads (where I/O operations such as file access or network communication account for most of the processing time), using more threads than CPU cores can be more effective.

If you do not call shutdown(), the program may hang and never terminate. Always call it using a try-finally block. For more advanced async processing, use CompletableFuture, which lets you compose and chain multiple asynchronous tasks.

For the basics of threads, see new Thread() / thread.start() / Runnable.

If you find any errors or copyright issues, please .