How to Use ExecutorService in Java: Simple Guide with Examples
Use
ExecutorService in Java to manage a pool of threads for running tasks asynchronously. Create an instance via Executors factory methods, submit tasks with submit() or execute(), and shut it down with shutdown() to free resources.Syntax
ExecutorService is an interface to manage thread pools and task execution. You create it using factory methods from the Executors class. Common methods include:
submit(Runnable/Callable): submits a task for execution.execute(Runnable): runs a task without returning a result.shutdown(): stops accepting new tasks and finishes existing ones.
java
ExecutorService executor = Executors.newFixedThreadPool(3); executor.submit(() -> { // task code here }); executor.shutdown();
Example
This example shows how to create an ExecutorService with a fixed thread pool, submit tasks that print messages, and then shut down the executor.
java
import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; public class ExecutorServiceExample { public static void main(String[] args) { ExecutorService executor = Executors.newFixedThreadPool(2); Runnable task1 = () -> System.out.println("Task 1 is running"); Runnable task2 = () -> System.out.println("Task 2 is running"); executor.submit(task1); executor.submit(task2); executor.shutdown(); } }
Output
Task 1 is running
Task 2 is running
Common Pitfalls
Common mistakes when using ExecutorService include:
- Not calling
shutdown(), which can cause the program to keep running indefinitely. - Using
execute()when you need a result; prefersubmit()for tasks that return values. - Ignoring exceptions thrown inside tasks, which can silently fail.
Always handle exceptions inside tasks and properly shut down the executor to avoid resource leaks.
java
/* Wrong way: forgetting to shutdown */ ExecutorService executor = Executors.newSingleThreadExecutor(); executor.submit(() -> System.out.println("Running task")); // Missing executor.shutdown(); /* Right way: */ ExecutorService executor2 = Executors.newSingleThreadExecutor(); executor2.submit(() -> { try { System.out.println("Running task safely"); } catch (Exception e) { e.printStackTrace(); } }); executor2.shutdown();
Output
Running task
Running task safely
Quick Reference
| Method | Description |
|---|---|
| newFixedThreadPool(int n) | Creates a thread pool with fixed number of threads |
| submit(Runnable/Callable) | Submits a task for execution and returns a Future |
| execute(Runnable) | Executes a task without returning a result |
| shutdown() | Stops accepting new tasks and finishes existing ones |
| shutdownNow() | Attempts to stop all running tasks immediately |
Key Takeaways
Create ExecutorService using Executors factory methods like newFixedThreadPool.
Submit tasks with submit() to get results or execute() for fire-and-forget.
Always call shutdown() to free resources and allow program to exit.
Handle exceptions inside tasks to avoid silent failures.
Use thread pools to efficiently manage multiple concurrent tasks.