ExecutorService in Java
Introduction
In Java, ExecutorService is part of the java.util.concurrent package and provides a high-level API for managing threads.
It helps in managing a pool of threads and executing tasks asynchronously without creating individual Thread objects.
Instead of manually managing threads, ExecutorService provides a thread pool and manages scheduling, execution, and lifecycle of threads efficiently.
Key Points:
- ExecutorService is an interface for asynchronous task execution.
- It provides thread pooling to reuse threads and improve performance.
- Supports scheduling, batch execution, and graceful shutdown.
How ExecutorService Works
When a task is submitted to an ExecutorService:
- The executor finds an available thread from its thread pool.
- If no thread is available, the task is queued.
- Threads in the pool execute tasks and then return to the pool.
Syntax:
ExecutorService executor = Executors.newFixedThreadPool(int nThreads);
Here
- nThreads = number of threads in the pool.
Example: Using ExecutorService
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class ExecutorServiceExample {
public static void main(String[] args) {
ExecutorService executor = Executors.newFixedThreadPool(3); // pool of 3 threads
Runnable task = () -> {
System.out.println(Thread.currentThread().getName() + " is executing a task.");
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + " finished task.");
};
for (int i = 0; i < 6; i++) {
executor.submit(task);
}
executor.shutdown();
}
}
Expected Output:
pool-1-thread-1 is executing a task.
pool-1-thread-2 is executing a task.
pool-1-thread-3 is executing a task.
pool-1-thread-1 finished task.
pool-1-thread-2 finished task.
pool-1-thread-3 finished task.
pool-1-thread-1 is executing a task.
pool-1-thread-2 is executing a task.
...
Key Methods in ExecutorService
| Method | Description |
|---|---|
| submit() | Submits a task for execution and returns a Future |
| execute() | Executes a task without returning a result |
| shutdown() | Initiates orderly shutdown |
| shutdownNow() | Attempts to stop all actively executing tasks |
| invokeAll() | Executes a collection of tasks |
| invokeAny() | Executes tasks and returns the result of one |
Advantages of CustomThreadPool
- Improves performance by reusing threads.
- Reduces overhead of thread creation.
- Useful for managing high-load applications.
Disadvantages
- More complex to implement than using built-in ExecutorService.
- Requires careful handling of synchronization.
- Needs manual shutdown and cleanup.
Real-World Use Case
CustomThreadPool can be useful for:
- Server applications handling multiple simultaneous requests.
- Parallel batch processing tasks.
- Any system requiring efficient thread reuse.
Conclusion
ExecutorService provides a robust way to manage threads without manually handling thread creation and lifecycle.
The custom thread pool implementation helps in understanding the core mechanics behind ExecutorService, thread pooling, and task scheduling.
For production, always use Java’s built-in Executors for stability, safety, and performance.
But building your own thread pool enhances understanding of concurrency deeply.
Next Blog- Custom implementation of ExecutorService in Java
