Executor Framework

The Executor Framework is part of the java.util.concurrent package introduced in Java 5 to simplify and standardize the process of concurrent task execution. It provides a high-level API for managing threads and asynchronous tasks, replacing the need to manually create and manage Thread objects.

Before the Executor Framework, Java developers had to manage threads using the Thread class directly. This led to:

  • Manual thread creation and destruction

  • Poor scalability

  • Difficulty in managing thread lifecycle

  • Inconsistent resource usage

The Executor Framework abstracts the creation, scheduling, execution, and lifecycle management of threads.

Core Concepts of the Executor Framework

Component Description
1. Executor Interface

– Provides a simple mechanism to execute tasks asynchronously.

– Core method: void execute(Runnable command) to execute a Runnable task.

2. ExecutorService Interface

– Extends Executor and adds task lifecycle management. – Supports submitting tasks that return results.

– Key methods include:   

 • submit() – submits tasks (Runnable or Callable)

 • shutdown() – initiates graceful shutdown    

• shutdownNow() – attempts to stop all tasks immediately    

• awaitTermination() – waits for tasks to complete post-shutdown

3. Executors Utility Class

– Provides static factory methods to create various thread pools:    

• newFixedThreadPool(int n)    

• newCachedThreadPool()    

• newSingleThreadExecutor()    

• newScheduledThreadPool(int corePoolSize)

 Program Implementation

A simple example demonstrating how to use the Executor Framework to manage and execute tasks.

Step-by-Step Example

//ExecutorDemo.java
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
class MyTask implements Runnable {
    private final int taskId;

    public MyTask(int taskId) {
        this.taskId = taskId;
    }

    @Override
    public void run() {
        System.out.println("Task " + taskId + " is running on " + Thread.currentThread().getName());
        try {
            Thread.sleep(2000); // Simulate some work
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        }
        System.out.println("Task " + taskId + " completed on " + Thread.currentThread().getName());
    }
}

class ExecutorDemo {
    public static void main(String[] args) {
        // Create a fixed thread pool with 3 threads
        ExecutorService executorService = Executors.newFixedThreadPool(3);

        // Submit tasks for execution
        for (int i = 0; i < 10; i++) {
            MyTask task = new MyTask(i);
            executorService.execute(task);
        }

        // Initiate an orderly shutdown
        executorService.shutdown();

        try {
            // Wait for previously submitted tasks to complete
            if (!executorService.awaitTermination(60, java.util.concurrent.TimeUnit.SECONDS)) {
                // Forcefully shutdown if tasks don't complete in 60 seconds
                executorService.shutdownNow();
            }
        } catch (InterruptedException ex) {
            // If current thread is interrupted during shutdown
            executorService.shutdownNow();
            Thread.currentThread().interrupt();
        }
    }
}

/*
C:\>javac ExecutorDemo.java

C:\>java ExecutorDemo
Task 0 is running on pool-1-thread-1
Task 1 is running on pool-1-thread-2
Task 2 is running on pool-1-thread-3
Task 0 completed on pool-1-thread-1
Task 3 is running on pool-1-thread-1
Task 1 completed on pool-1-thread-2
Task 4 is running on pool-1-thread-2
Task 2 completed on pool-1-thread-3
Task 5 is running on pool-1-thread-3
Task 3 completed on pool-1-thread-1
Task 6 is running on pool-1-thread-1
Task 5 completed on pool-1-thread-3
Task 4 completed on pool-1-thread-2
Task 7 is running on pool-1-thread-3
Task 8 is running on pool-1-thread-2
Task 8 completed on pool-1-thread-2
Task 6 completed on pool-1-thread-1
Task 7 completed on pool-1-thread-3
Task 9 is running on pool-1-thread-2
Task 9 completed on pool-1-thread-2

C:\>java ExecutorDemo
Task 1 is running on pool-1-thread-2
Task 0 is running on pool-1-thread-1
Task 2 is running on pool-1-thread-3
Task 1 completed on pool-1-thread-2
Task 3 is running on pool-1-thread-2
Task 2 completed on pool-1-thread-3
Task 0 completed on pool-1-thread-1
Task 4 is running on pool-1-thread-3
Task 5 is running on pool-1-thread-1
Task 3 completed on pool-1-thread-2
Task 6 is running on pool-1-thread-2
Task 4 completed on pool-1-thread-3
Task 7 is running on pool-1-thread-3
Task 5 completed on pool-1-thread-1
Task 8 is running on pool-1-thread-1
Task 6 completed on pool-1-thread-2
Task 9 is running on pool-1-thread-2
Task 7 completed on pool-1-thread-3
Task 8 completed on pool-1-thread-1
Task 9 completed on pool-1-thread-2

C:\>java ExecutorDemo
Task 2 is running on pool-1-thread-3
Task 0 is running on pool-1-thread-1
Task 1 is running on pool-1-thread-2
Task 2 completed on pool-1-thread-3
Task 3 is running on pool-1-thread-3
Task 0 completed on pool-1-thread-1
Task 4 is running on pool-1-thread-1
Task 1 completed on pool-1-thread-2
Task 5 is running on pool-1-thread-2
Task 3 completed on pool-1-thread-3
Task 4 completed on pool-1-thread-1
Task 6 is running on pool-1-thread-3
Task 7 is running on pool-1-thread-1
Task 5 completed on pool-1-thread-2
Task 8 is running on pool-1-thread-2
Task 6 completed on pool-1-thread-3
Task 7 completed on pool-1-thread-1
Task 9 is running on pool-1-thread-3
Task 8 completed on pool-1-thread-2
Task 9 completed on pool-1-thread-3

*/

Explanation of the Example

Step-1:Task Definition:
  • MyTask class implements Runnable, providing the code that will be run by a thread in the pool.
  • Each task prints its ID and the name of the thread running it, simulates work with sleep, and then prints a completion message.
Step-2: ExecutorService Creation:
  • newFixedThreadPool(3) creates a thread pool with 3 threads.
Step-3: Task Submission:
  • A loop submits 10 instances of MyTask to the ExecutorService.
  • The execute method queues the tasks for execution by the thread pool.
Step-4: Shutdown:
  • shutdown() initiates an orderly shutdown where previously submitted tasks are executed, but no new tasks are accepted.
  • awaitTermination(60, TimeUnit.SECONDS) waits for 60 seconds for all tasks to complete.
  • If tasks do not complete within 60 seconds, shutdownNow() is called to attempt to stop all actively executing tasks and halt the processing of waiting tasks.

Comparison: Thread Vs Executor Framework

Feature Thread Class Executor Framework
Thread Management Manual Automatic
Resource Efficiency Low High
Return Values Not possible Possible with Callable
Exception Handling Manual Integrated
Scalability Poor Excellent

The Executor Framework is a robust solution for handling concurrency in Java. It:

  • Abstracts thread management

  • Encourages best practices

  • Improves performance and scalability

  • Supports task scheduling, result tracking, and controlled shutdown

It is a foundation of modern Java multithreading and is widely used in real-world applications, web servers, batch jobs, and asynchronous systems.

Scroll to Top