- What is the Runnable Interface?
- Why Use Runnable?
- Runnable vs Extending Thread Class
- How to Implement Runnable in Java
- Example 1: Creating and Running a Thread Using Runnable
- Explanation
- Example 2: Printing a Welcome Message for Multiple Users
- Step-by-Step Explanation:
- 1. class WelcomeTask implements Runnable
- 2. Constructor WelcomeTask(String userName)
- 3. public void run()
- 4. Creating Threads
- 5. Starting Threads
- How Runnable Works Internally
- Summary Flow:
- Java 8 Runnable with Lambda
- Explanation:
- Benefits of Using Lambda with Runnable:
- Advantages of Using Runnable
Multithreading is a powerful feature of Java that allows concurrent execution of two or more parts of a program. One of the foundational components of Java’s multithreading is the Runnable interface.
What is the Runnable Interface?
The Runnable interface is a functional interface in Java defined in the java.lang package. It is used to represent a task that can be executed by a thread.
@FunctionalInterface
public interface Runnable {
public abstract void run();
}
As you can see, the interface has only one method, run(). This method is meant to contain the code that you want the thread to execute.
Why Use Runnable?
You use Runnable when:
- You want to execute code in a separate thread.
- You want to share a common resource or object among multiple threads.
- You want to inherit from another class (since Java doesn’t support multiple inheritance of classes).
Runnable vs Extending Thread Class
| Feature | Runnable Interface | Thread Class |
|---|---|---|
| Inheritance | Can extend another class | Cannot extend any other class |
| Code Sharing | Easier to share resources | Not easy to share resources |
| Recommended Use | Preferred in real-world projects | Mostly used in simple cases or learning |
| Flexibility | High (only implements interface) | Low (inherits whole thread class) |
How to Implement Runnable in Java
Example 1: Creating and Running a Thread Using Runnable
class MyRunnable implements Runnable {
public void run() {
for (int i = 1; i <= 5; i++) {
System.out.println("Runnable thread: " + i);
}
}
}
public class RunnableExample {
public static void main(String[] args) {
MyRunnable runnable = new MyRunnable();
Thread thread = new Thread(runnable);
thread.start(); // starts a new thread
}
}
Output:
Runnable thread: 1
Runnable thread: 2
Runnable thread: 3
Runnable thread: 4
Runnable thread: 5
Explanation
- Implements Runnable:
MyRunnableclass implements theRunnableinterface, meaning it must define arun()method that contains the code to be run by a thread. - run() Method:
This method prints “Runnable thread: 1” to “Runnable thread: 5” using a loop. - Creating Thread:
Inmain(), we create an object ofMyRunnableand pass it to aThreadconstructor. - Starting Thread:
thread.start()starts a new thread and internally calls therun()method.
Example 2: Printing a Welcome Message for Multiple Users
Imagine you’re building a system where multiple users log into a website, and each user should be welcomed in a separate thread. We’ll simulate this by using the Runnable interface to print a welcome message multiple times — as if greeting each user independently in a thread.
// Step 1: Create a class that implements Runnable
class WelcomeTask implements Runnable {
private String userName;
// Constructor to receive the user's name
WelcomeTask(String userName) {
this.userName = userName;
}
// Step 2: Override the run() method to define thread's behavior
public void run() {
for (int i = 1; i <= 3; i++) {
System.out.println("Welcome " + userName + " - message " + i);
try {
Thread.sleep(500); // adding delay to simulate processing
} catch (InterruptedException e) {
System.out.println("Thread interrupted for user: " + userName);
}
}
}
}
// Step 3: Create and start threads in the main class
public class RunnableExample {
public static void main(String[] args) {
// Creating tasks for different users
WelcomeTask user1 = new WelcomeTask("Alice");
WelcomeTask user2 = new WelcomeTask("Bob");
// Wrapping each task in a Thread object
Thread thread1 = new Thread(user1);
Thread thread2 = new Thread(user2);
// Starting both threads
thread1.start();
thread2.start();
}
}
Output (Note: Output order may vary due to thread scheduling.)
Welcome Alice - message 1
Welcome Bob - message 1
Welcome Alice - message 2
Welcome Bob - message 2
Welcome Alice - message 3
Welcome Bob - message 3
Step-by-Step Explanation:
1. class WelcomeTask implements Runnable
- We’re creating a class
WelcomeTaskthat implements theRunnableinterface. - This class will define what task we want to perform in a separate thread.
2. Constructor WelcomeTask(String userName)
- We use a constructor to initialize the user’s name.
- Each instance of
WelcomeTaskrepresents a specific user.
3. public void run()
- The
run()method contains the code that will execute in the new thread. - It prints a welcome message three times for the specific user.
Thread.sleep(500)pauses the thread for 500 milliseconds to simulate time taken by a real task (like database access or server response).
4. Creating Threads
Thread thread1 = new Thread(user1);
Thread thread2 = new Thread(user2);
- We wrap our
Runnableobject inside aThreadobject. - This is required because only
Threadhas thestart()method.
5. Starting Threads
thread1.start();
thread2.start();
- Starts both threads.
- Each thread will call the
run()method of its correspondingRunnableobject.
How Runnable Works Internally
1. You create a class that implements Runnable
- This class defines the task you want to run in a separate thread.
- It must override the run() method from the Runnable interface.
class MyTask implements Runnable {
public void run() {
System.out.println("Task running...");
}
}
2. You override the run() method
- This method contains the actual logic that will run when the thread starts.
- No return value, no parameters.
3. You create a Thread object and pass the Runnable instance to it
- The
Threadconstructor accepts aRunnableobject. - This binds the task to the thread.
MyTask task = new MyTask();
Thread thread = new Thread(task);
4. You call start() on the Thread object
- This creates a new OS-level thread and then calls the thread’s internal
run()method in the background.
thread.start(); // starts new thread, runs task.run()
5. Internally, start() triggers run() on a new thread
start()sets up a new call stack and executesRunnable.run()from there.- If you call
run()directly (withoutstart()), the code runs in the main thread, no new thread is created.
Summary Flow:
You → implement Runnable → override run() → pass to Thread → call start() →
JVM → creates a new thread → calls run() in that thread
Java 8 Runnable with Lambda
Since Runnable is a functional interface, you can use lambda expressions (Java 8+) for more concise code:
public class LambdaRunnable {
public static void main(String[] args) {
Runnable task = () -> {
for (int i = 1; i <= 3; i++) {
System.out.println("Lambda Thread: " + i);
}
};
Thread thread = new Thread(task);
thread.start();
}
}
Output
Lambda Thread: 1
Lambda Thread: 2
Lambda Thread: 3
Explanation:
1. Runnable is a functional interface
- A functional interface has only one abstract method (
run()in this case). - Java 8 allows you to use lambda expressions to write such interfaces more concisely.
2. Using Lambda Expression:
Runnable task = () -> {
// code inside run() method
};
- This replaces the need to create a separate class that implements
Runnable. - It’s a shortcut way of saying:
“Run this block of code in a separate thread.”
3. Creating and Starting the Thread:
Thread thread = new Thread(task);
thread.start();
- A new
Threadis created with the lambdaRunnabletask. - When
start()is called, it runs the code inside the lambda in a new thread.
Benefits of Using Lambda with Runnable:
- Less code: No need to create a separate class.
- Cleaner and readable.
- Modern style using Java 8+ features.
Advantages of Using Runnable
- Better resource sharing: Multiple threads can share the same
Runnableobject. - Promotes clean code: Keeps your class hierarchy clean by allowing you to extend other classes.
- Functional Interface: Works seamlessly with lambda expressions.
- Separation of concerns: Logic of the task is separate from the thread management.