The Runnable interface is part of the java.lang package and is used to define a task that can be executed by a thread. It provides a way to achieve multithreading by separating the task logic from the thread execution mechanism.
- It contains a single abstract method run() that holds the code executed by the thread.
- It is preferred over extending the Thread class as it supports better design and flexibility.

Example: Implementing Runnable
class MyTask implements Runnable{
@Override
public void run() {
System.out.println("Thread is running using Runnable interface");
}
}
public class GFG{
public static void main(String[] args) {
MyTask task = new MyTask();
Thread t = new Thread(task);
t.start(); // starts a new thread
}
}
Output
Thread is running using Runnable interface
Explanation:
- MyTask implements the Runnable interface
- The run() method contains the code executed by the thread
- A Thread object is created by passing the Runnable object
- Calling start() creates a new thread and internally calls run()
Declaration
public interface Runnable {
void run();
}
Steps to Implement Runnable Interface
Step 1: Implement Runnable
Create a class that implements the Runnable interface and override the run() method to define the task to be executed by the thread.
class MyTask implements Runnable {
@Override
public void run() {
System.out.println("Thread is running");
}
}
Step 2: Create Thread Object
Create a Thread object by passing the Runnable instance and call start() to execute the task in a new thread.
public class GFG{
public static void main(String[] args){
MyTask task = new MyTask();
Thread t = new Thread(task);
t.start(); // starts a new thread
}
}
Runnable with Lambda Expression
Since Runnable is a functional interface, it can be written using lambda expressions.
public class GFG{
public static void main(String[] args){
Runnable task = () -> {
System.out.println("Thread running using lambda");
};
Thread t = new Thread(task);
t.start();
}
}
Output
Thread running using lambda
Explanation: This code creates a Runnable using a lambda expression, where the lambda body represents the run() method logic. The Runnable is passed to a Thread object, and calling start() creates a new thread that executes the code inside the lambda.
Runnable with Executor Framework
The Executor Framework provides a high-level API for managing threads efficiently. Instead of creating threads manually, tasks are submitted to a thread pool.
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class GFG{
public static void main(String[] args){
ExecutorService executor = Executors.newFixedThreadPool(2);
executor.execute(() -> {
System.out.println("Task executed by Executor");
});
executor.shutdown();
}
}
Output
Task executed by Executor
Explanation:
- ExecutorService manages thread creation and reuse
- newFixedThreadPool(2) creates a pool of 2 threads
- execute() submits a Runnable task
- shutdown() releases resources gracefully
Handling Exception in Runnable
In Java, exceptions in a Runnable must be handled inside the run() method because run() cannot throw checked exceptions. If not handled, the exception terminates the thread.
class MyTask implements Runnable {
public void run() {
try {
int result = 10 / 0; // ArithmeticException
} catch (ArithmeticException e) {
System.out.println("Exception handled inside Runnable");
}
}
}
public class Main {
public static void main(String[] args) {
Thread t = new Thread(new MyTask());
t.start();
}
}
Output
Exception handled inside Runnable
Explanation:
- run() cannot declare throws for checked exceptions
- Runtime exceptions like ArithmeticException must be handled manually
- If not caught, the JVM terminates the thread
Runnable Interface vs Thread Class
| Point | Runnable Interface | Thread Class |
|---|---|---|
| Type | It is an interface used to define a task. | It is a class used to create and control a thread. |
| Inheritance | Allows a class to extend another class. | Does not allow extending any other class. |
| Code Reusability | Provides better reusability by separating task logic. | Less reusable as task and thread are tightly coupled. |
| Memory Usage | Uses less memory as threads are created separately. | Uses more memory due to thread inheritance. |
| Preferred Usage | Recommended for multithreading. | Less preferred compared to Runnable. |