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);
}
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.

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
ExecutorServiceto 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.
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.