DEV Community

Munaf Badarpura
Munaf Badarpura

Posted on

Java Executor Framework Tutorial: Simplifying Multithreading with ExecutorService

In Java, Managing threads manually can be a complex task because it involves thread creation, synchronization and also thread lifecycle management. to simplifying the Java Executor Framework, part of the java.util.concurrent package, provides a robust solution to handle these complexities with ease.

It abstracts thread management and allows developers to focus on task execution. So in this blog we explores the Executor Framework, its components, and practical usage with examples.

What is the Executor Framework?

The Executor Framework is a high-level API designed to manage threads and execute tasks asynchronously. Instead of directly creating and managing Thread objects, you can use the framework to submit tasks and let it handle the underlying thread pool. At its core, the framework revolves around the Executor interface, with ExecutorService extending it to offer advanced features.

Key Components

  • Executor: The base interface defining a simple task execution mechanism.
  • ExecutorService: An extension of Executor that provides methods to manage task submission, shutdown, and thread pools.
  • ThreadPoolExecutor: A concrete implementation that manages a pool of threads, configurable with core and maximum pool sizes.
  • ScheduledExecutorService: A specialized service for scheduling tasks to run after a delay or at fixed intervals.
  • ForkJoinPool: Optimized for tasks that can be recursively split into smaller subtasks.

2.png

Why Use the Executor Framework?

  1. Simplified Thread Management: No need to manually create or destroy threads.
  2. Thread Reuse: Reduces overhead by reusing threads from a pool.
  3. Flexible Task Submission: Supports Runnable and Callable tasks with Future results.
  4. Controlled Shutdown: Offers graceful termination with shutdown() and shutdownNow().

How It Works

The Executor Framework uses a thread pool to manage tasks. Submitters send tasks to the ExecutorService, which queues them in a task queue (e.g., ArrayBlockingQueue or LinkedBlockingQueue). A pool of threads picks tasks from the queue and executes them. This process is illustrated by the diagram showing task submission, queuing, and execution by threads.

1.png

Configuring a ThreadPoolExecutor

A ThreadPoolExecutor can be customized with parameters:

  • Core Pool Size: Minimum number of threads kept alive (e.g., 4).
  • Maximum Pool Size: Maximum number of threads that can be created (e.g., 7).
  • Keep Alive Time: Idle time after which extra threads are terminated (e.g., 2 seconds).
  • Task Queue: A queue to hold pending tasks (e.g., LinkedBlockingQueue).

Example configuration:

ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(
    4,      // corePoolSize
    7,      // maximumPoolSize
    2,      // keepAliveTime (seconds)
    TimeUnit.SECONDS,
    new LinkedBlockingQueue<>()
);
Enter fullscreen mode Exit fullscreen mode

Submitting Tasks

Tasks can be submitted in two main ways:

  • execute(Runnable): Fire-and-forget execution, suitable for tasks without return values.
  • submit(Runnable/Callable): Returns a Future object to track task completion or retrieve results.

Example: Submitting a Runnable Task

threadPoolExecutor.submit(new Runnable() {
    @Override
    public void run() {
        System.out.println("Task 1(4Seconds) Started by Thread Name : " + Thread.currentThread().getName());
        try {
            Thread.sleep(4000);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
        System.out.println("Task 1(4Seconds) Ended by Thread Name : " + Thread.currentThread().getName());
    }
});

Enter fullscreen mode Exit fullscreen mode

This code submits a task that sleeps for 4 seconds, printing the thread name before and after.

Shutting Down the Executor

To terminate the thread pool gracefully:

  • shutdown(): Initiates a shutdown, completing ongoing tasks but not accepting new ones.
  • shutdownNow(): Attempts to stop all tasks immediately, interrupting active threads.

Example:

threadPoolExecutor.shutdown();
Enter fullscreen mode Exit fullscreen mode

Read complete blog here : https://www.codingshuttle.com/blogs/java-executor-framework-tutorial-simplifying-multithreading-with-executor-service/

Top comments (0)