Difference between Runnable and Thread in Java

1. Introduction

In Java, multithreading is a core feature that allows concurrent execution of two or more threads. Runnable and Thread are two ways to create threads, but they serve different purposes. Runnable is an interface that represents a task to be run by a thread, while Thread is a class that encapsulates the behavior of a thread.

2. Key Points

1. Runnable is an interface with a single run() method that needs to be implemented to define the task that will execute in the thread.

2. Thread is a class that can be extended to create a new thread and override the run() method to define its task.

3. Creating a thread with Runnable allows you to extend another class, but extending Thread does not.

4. Using Runnable is the preferred way to create a thread because it supports the Object-Oriented principle of composition over inheritance.

3. Differences

Runnable Thread
The Runnable interface must be implemented by any class whose instances are intended to be executed by a thread. A Thread class represents a thread of execution in a program.
This defines a single method run() without any implementation that must be implemented by classes that use it. Provides the run() method, among others, and can be subclassed to override the run() method with specific behavior.
Allows greater flexibility and avoids the Java single inheritance limitation, as a class can implement multiple interfaces. Extending the Thread class means a class cannot extend any other class due to Java’s single inheritance model.
To use a Runnable, you must instantiate a Thread or Executor and pass the Runnable object to it. A Thread instance can be created and started directly by calling its start() method.
More suited for classes that already extend another class and want to be runnable. Suitable when planning to override other Thread methods in addition to run(), or manage threads directly.

4. Example

// Step 1: Implement Runnable interface
class RunnableTask implements Runnable {
    public void run() {
        System.out.println("Runnable task is running.");
    }
}

// Step 2: Extend Thread class
class ThreadTask extends Thread {
    public void run() {
        System.out.println("Thread task is running.");
    }
}

public class Main {
    public static void main(String[] args) {
        // Step 3: Start the Runnable task
        Runnable task1 = new RunnableTask();
        Thread thread1 = new Thread(task1);
        thread1.start();

        // Step 4: Start the Thread task
        ThreadTask task2 = new ThreadTask();
        task2.start();
    }
}

Output:

Runnable task is running.
Thread task is running.

Explanation:

1. RunnableTask implements Runnable and defines what the thread will do in the run() method.

2. ThreadTask extends Thread and also defines the thread's task in the run() method.

3. A Thread object is created and given a RunnableTask to run, and then started with thread1.start().

4. A ThreadTask object, which is a Thread, is started directly with task2.start().

5. When to use?

- Use Runnable when you want to separate the task's logic from thread control or when you need to implement multiple interfaces.

- Use Thread when you need to manage or control thread-specific behavior and do not require the ability to extend another class.

Comments