☕ Java Q18 / 105

What is the difference between Runnable and Thread?

AI-Powered Answer ✓ Answered

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.

java
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 (the Thread object) are tightly bound.
  • Each instance of your custom Thread class 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.

java
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 Runnable and 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 Runnable object can be shared among multiple Thread instances, 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
TypeClass (`java.lang.Thread`)Interface (`java.lang.Runnable`)
ImplementationExtend `Thread` classImplement `Runnable` interface
Task DefinitionOverride `run()` method directly in the extended class.Implement `run()` method in the implementing class.
InheritanceLimited (cannot extend another class)Flexible (can extend another class and implement `Runnable`)
CouplingTightly coupled (task and thread are one entity)Loosely coupled (task is separate from the thread executor)
Resource SharingMore 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 ScenarioWhen 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.
RecommendationLess preferred in most modern Java applications.Generally preferred and considered best practice in Java.