What is the difference between Runnable and Thread?
In Java, both `Runnable` and `Thread` are fundamental concepts used for implementing multithreading. While both achieve concurrency, they represent different approaches and have distinct characteristics regarding how a task is defined and executed.
The `Thread` Class
The java.lang.Thread class is a concrete implementation of a thread. When you extend the Thread class, your class itself becomes a thread, and you define the thread's execution logic by overriding its run() method. To start the thread, you create an instance of your custom Thread class and call its start() method.
class MyThread extends Thread {
public void run() {
System.out.println("Thread created by extending Thread class. ID: " + Thread.currentThread().getId());
}
public static void main(String[] args) {
MyThread t1 = new MyThread();
t1.start(); // Invokes run() method
}
}
Key Points of `Thread` Class
- Class-based approach: Your class *is* a thread, meaning the task and the thread itself are combined.
- Limited to single inheritance: Java does not support multiple inheritance, so if your class already extends another class, you cannot extend
Thread. - Tightly coupled: The task (defined in
run()) and the mechanism for execution (theThreadobject) are tightly bound. - Each instance of your custom
Threadclass creates a new thread.
The `Runnable` Interface
The java.lang.Runnable interface defines a single method, run(), which contains the code to be executed by a thread. When you implement Runnable, your class defines a task that can be executed by a Thread object. You create an instance of your Runnable class, then pass it to the constructor of a Thread object, and finally call start() on the Thread object.
class MyRunnable implements Runnable {
public void run() {
System.out.println("Thread created by implementing Runnable interface. ID: " + Thread.currentThread().getId());
}
public static void main(String[] args) {
MyRunnable runnable = new MyRunnable();
Thread t1 = new Thread(runnable); // Pass runnable object to Thread constructor
t1.start(); // Invokes run() method of MyRunnable
// You can also reuse the runnable object for multiple threads:
Thread t2 = new Thread(runnable);
t2.start();
}
}
Key Points of `Runnable` Interface
- Interface-based approach: Your class *defines* a task for a thread, separating the task from the thread object itself.
- Supports multiple inheritance indirectly: Since it's an interface, your class can implement
Runnableand still extend another class. - Loose coupling: Promotes better design by separating the task (what to run) from the thread (how to run it).
- Resource sharing: A single
Runnableobject can be shared among multipleThreadinstances, allowing for easier sharing of common data. - Recommended approach: Generally preferred in Java for multithreading due to its flexibility and better design principles.
Comparative Table
| Feature | `Thread` Class | `Runnable` Interface |
|---|---|---|
| Type | Class (`java.lang.Thread`) | Interface (`java.lang.Runnable`) |
| Implementation | Extend `Thread` class | Implement `Runnable` interface |
| Task Definition | Override `run()` method directly in the extended class. | Implement `run()` method in the implementing class. |
| Inheritance | Limited (cannot extend another class) | Flexible (can extend another class and implement `Runnable`) |
| Coupling | Tightly coupled (task and thread are one entity) | Loosely coupled (task is separate from the thread executor) |
| Resource Sharing | More complex if multiple threads of the *same* custom `Thread` class instance need to share state (requires static or external shared objects). | Easier to share a single `Runnable` instance among multiple `Thread` objects. |
| Usage Scenario | When the class *is* inherently a thread and no other inheritance is needed. | When the class defines a task that can be executed by a thread, promoting modularity and reuse. |
| Recommendation | Less preferred in most modern Java applications. | Generally preferred and considered best practice in Java. |