ExecutorService
Table of Contents
What is an ExecutorService #
The ExecutorService interface simplifies the managment of threads in a multithreaded environment.
The ExecutorService is part of the java.util.concurrent package, introduced in Java 5, which provides high-level concurrency utilities for managing and executing threads. The ExecutorService makes it easier to develop concurrent applications in Java by abstracting away the complexities of thread creation, lifecycle management, and task submission.
Features of the ExecutorService #
The ExecutorService provides the following features:
-
Task Execution: It provides a way to submit tasks for execution, such as Runnable or Callable objects, and manages the execution of these tasks on a pool of worker threads.
-
Thread Pool Management: It manages a pool of worker threads, which can be reused to execute multiple tasks. This helps to reduce the overhead of creating and destroying threads for each task. Thread creation can be expensive, so reusing threads can improve performance.
-
Task Scheduling: It provides methods for scheduling tasks to run after a certain delay or at regular intervals.
-
Task Completion: It provides methods for tracking the completion of tasks, such as waiting for all tasks to complete or retrieving the results of completed tasks.
-
Exception Handling: It provides mechanisms for handling exceptions that occur during task execution, such as propagating exceptions to the calling code or logging them.
-
Thread Lifecycle Management: It provides methods for controlling the lifecycle of the executor, such as starting and shutting down the executor, and waiting for tasks to complete before shutting down.
Think of the ExecutorService holding a pool of threads that can be used to execute tasks. The ExecutorService manages the lifecycle of these threads, and provides a way to submit tasks for execution.
ExecutorService Interface #
The ExecutorService is the interface that is used to manage this thread pool and execute tasks. It extends the Executor interface, which provides a single method for executing tasks, and adds additional methods for managing the lifecycle of the executor and controlling the execution of tasks.
Common methods of the ExecutorService interface include:
-
submit(Runnable task): Submits a Runnable task for execution and returns a Future representing the result of the task. -
submit(Callable task): Submits a Callable task for execution and returns a Future representing the result of the task. -
shutdown(): Initiates an orderly shutdown of the executor, allowing previously submitted tasks to execute before terminating. -
shutdownNow(): Attempts to stop all actively executing tasks, halts the processing of waiting tasks, and returns a list of the tasks that were awaiting execution.
Types of ExecutorService #
The various implementations of the ExecutorService can be created using the Executors class, which provides factory methods for creating different types of executorservices. The following are some of the common types of executorservices, and the factory method used to create them.
SingleThreadExecutor #
Creates an executor that uses a single worker thread to execute tasks sequentially.
ExecutorService executor = Executors.newSingleThreadExecutor();
FixedThreadPool #
Creates an executor that uses a fixed number of worker threads to execute tasks concurrently.
ExecutorService executor = Executors.newFixedThreadPool(5);
CachedThreadPool #
Creates an executor that uses a dynamic number of worker threads to execute tasks concurrently, which can be reused if available or created if needed.
ExecutorService executor = Executors.newCachedThreadPool();
ScheduledThreadPool #
Creates an executor that can schedule tasks to run after a certain delay or at regular intervals.
ScheduledExecutorService executor =
Executors.newScheduledThreadPool(5);
Example Usage #
The following example demonstrates how to create an ExecutorService and submit a tasks for execution.
import java.util.concurrent.ExecutorService;
public class ExecutorServiceExample {
public static void main(String[] args) {
// Create a fixed thread pool with 5 worker threads
ExecutorService executor = Executors.newFixedThreadPool(5);
// Submit a Runnable for execution (using a lambda expression)
executor.submit(() -> System.out.println("Hello, ExecutorService!"));
// Shutdown the executor
executor.shutdown();
}
}