Java.util.concurrent.Executor interface with Examples

Last Updated : 26 Mar, 2026

The Executor interface in Java provides a high-level mechanism to execute tasks asynchronously without directly managing threads. It acts as a replacement for manually creating and controlling Thread objects. Executors submit Runnable tasks for execution and manage the underlying threads efficiently.

  • Simplifies thread management and decouples task submission from execution.
  • Can execute tasks in a new thread, pooled thread, or the calling thread.
  • Forms the foundation for higher-level concurrency utilities like ExecutorService and ScheduledExecutorService.

Declaration Syntax

public interface Executor {
void execute(Runnable command);
}

Java
import java.util.concurrent.Executor;
import java.util.concurrent.RejectedExecutionException;

public class ExecutorDemo {
    public static void main(String[] args) {
        ExecutorImp obj = new ExecutorImp();
        try {
            obj.execute(new NewThread());
        } catch (RejectedExecutionException | NullPointerException exception) {
            System.out.println(exception);
        }
    }
}

class ExecutorImp implements Executor {
    @Override
    public void execute(Runnable command) {
        new Thread(command).start();  // Starts the task in a new thread
    }
}

class NewThread implements Runnable {
    @Override
    public void run() {
        System.out.println("Thread executed under an executor");
    }
}

Output
Thread executed under an executor

Explanation: ExecutorImp implements the Executor interface and overrides execute() to run the task in a new thread. When execute() is called, the NewThread task runs and prints the message.

Executor Interface Class Hierarchy: 

These are the common classes that implement Executor or its sub-interfaces to provide thread pooling and scheduling features.

executorinterface_hierarchy
Hierarchy

Implementing Classes

  • AbstractExecutorService: Base class implementing ExecutorService providing common methods.
  • ForkJoinPool: Executes tasks that can be broken into smaller subtasks (supports work-stealing).
  • ScheduledThreadPoolExecutor: Executes tasks after a given delay or periodically.
  • ThreadPoolExecutor: Manages a pool of worker threads for executing tasks efficiently.

Implementing Sub-Interfaces of Executor

The Executor interface has two main sub-interfaces that extend its functionality:

1. ExecutorService

  • Provides methods to manage thread life cycle, submit tasks, and get results.
  • Allows submitting both Runnable and Callable tasks.

2. ScheduledExecutorService

  • Extends ExecutorService to allow scheduling tasks with a delay or at fixed intervals.
  • Useful for periodic tasks like timers, scheduled updates, or repeated background jobs.

Method of Executor interface: 

execute(Runnable command): Submits a task for execution. The task may run in a new thread, a thread pool, or the calling thread.

Java
import java.util.concurrent.Executor;

public class MultiTaskExecutorDemo {
    public static void main(String[] args) {
        Executor executor = new SimpleExecutor();

        // Submitting three tasks to executor
        executor.execute(() -> System.out.println("Task 1 executed"));
        executor.execute(() -> System.out.println("Task 2 executed"));
        executor.execute(() -> System.out.println("Task 3 executed"));
    }
}

// Custom executor implementing Executor interface
class SimpleExecutor implements Executor {
    @Override
    public void execute(Runnable task) {
        new Thread(task).start(); // Runs each task in a separate thread
    }
}

Output
Task 1 executed
Task 2 executed
Task 3 executed

Explanation: SimpleExecutor implements the Executor interface and overrides execute() to start each submitted task in a new thread. We submit three tasks using lambda expressions, and each prints a message asynchronously.
 

Comment