Runnable vs Thread in Java

Introduction

In Java, multithreading can be achieved through two main approaches: extending the Thread class and implementing the Runnable interface. Both approaches enable concurrent execution of tasks, but they have distinct differences and use cases. Understanding these differences is crucial for effective multithreading.

Table of Contents

  1. Overview of Thread and Runnable
  2. Key Differences between Thread and Runnable
  3. When to Use Runnable
  4. When to Use Thread
  5. Example: Extending Thread Class
  6. Example: Implementing Runnable Interface
  7. Comparison Table
  8. Conclusion

1. Overview of Thread and Runnable

Thread Class

The Thread class represents a thread of execution in a Java program. By extending the Thread class, you can create a new thread by defining its behavior in the run method.

Syntax:

public class MyThread extends Thread {
    @Override
    public void run() {
        // Code to be executed by the thread
    }
}

Runnable Interface

The Runnable interface should be implemented by any class whose instances are intended to be executed by a thread. The Runnable interface has a single method, run, which must be implemented to define the code executed by the thread.

Syntax:

public class MyRunnable implements Runnable {
    @Override
    public void run() {
        // Code to be executed by the thread
    }
}

2. Key Differences between Thread and Runnable

  1. Inheritance vs. Composition:

    • Thread: Uses inheritance. Your class must extend the Thread class.
    • Runnable: Uses composition. Your class implements the Runnable interface, and you pass an instance of your class to a Thread object.
  2. Flexibility:

    • Thread: Your class cannot extend any other class if it extends Thread.
    • Runnable: Your class can extend another class since it only implements Runnable.
  3. Resource Sharing:

    • Thread: Each thread object creates a unique thread.
    • Runnable: Multiple threads can share the same Runnable object, making it more suitable for resource sharing.
  4. Decoupling Task from Execution:

    • Thread: Task and thread are tightly coupled.
    • Runnable: Task and thread are decoupled, leading to better design and reuse.

3. When to Use Runnable

  • When Your Class Needs to Extend Another Class: Since Java does not support multiple inheritance, implementing Runnable allows your class to extend another class.
  • When You Want to Share Resources: If you need multiple threads to share the same resource, implementing Runnable and passing the same Runnable instance to multiple Thread objects is preferred.
  • When You Want Better Design: Implementing Runnable leads to a cleaner separation between the task to be performed and the thread executing the task.

4. When to Use Thread

  • When You Want to Override Other Thread Methods: If you need to override other Thread methods (like start, sleep, etc.), extending Thread may be more convenient.
  • When You Prefer Simplicity for Small Applications: For small applications or quick prototypes, extending Thread can be simpler and more straightforward.

5. Example: Extending Thread Class

Example:

class MyThread extends Thread {
    @Override
    public void run() {
        for (int i = 0; i < 5; i++) {
            System.out.println(Thread.currentThread().getName() + " is running. Count: " + i);
            try {
                Thread.sleep(1000);  // Simulate some work with sleep
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

public class ThreadExample {
    public static void main(String[] args) {
        MyThread thread1 = new MyThread();
        MyThread thread2 = new MyThread();

        thread1.start();
        thread2.start();
    }
}

Output:

Thread-0 is running. Count: 0
Thread-1 is running. Count: 0
Thread-0 is running. Count: 1
Thread-1 is running. Count: 1
Thread-0 is running. Count: 2
Thread-1 is running. Count: 2
Thread-0 is running. Count: 3
Thread-1 is running. Count: 3
Thread-0 is running. Count: 4
Thread-1 is running. Count: 4

6. Example: Implementing Runnable Interface

Example:

class MyRunnable implements Runnable {
    @Override
    public void run() {
        for (int i = 0; i < 5; i++) {
            System.out.println(Thread.currentThread().getName() + " is running. Count: " + i);
            try {
                Thread.sleep(1000);  // Simulate some work with sleep
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

public class RunnableExample {
    public static void main(String[] args) {
        MyRunnable myRunnable = new MyRunnable();
        Thread thread1 = new Thread(myRunnable);
        Thread thread2 = new Thread(myRunnable);

        thread1.start();
        thread2.start();
    }
}

Output:

Thread-0 is running. Count: 0
Thread-1 is running. Count: 0
Thread-0 is running. Count: 1
Thread-1 is running. Count: 1
Thread-0 is running. Count: 2
Thread-1 is running. Count: 2
Thread-0 is running. Count: 3
Thread-1 is running. Count: 3
Thread-0 is running. Count: 4
Thread-1 is running. Count: 4

7. Comparison Table

Feature Thread Runnable
Approach Inherits Thread class Implements Runnable interface
Inheritance Cannot extend other classes Can extend other interfaces
Resource Sharing Not as easy Easy
Task and Execution Decoupling No Yes
Flexibility Less flexible More flexible
Design Less reusable More reusable
Code Simplicity Simpler for small applications Better for complex applications

8. Conclusion

Choosing between extending the Thread class and implementing the Runnable interface depends on your specific use case. Implementing Runnable is generally preferred due to its flexibility, ability to share resources, and better design practices. Extending Thread can be simpler for small applications or quick prototypes but comes with limitations such as inability to extend other classes.

By understanding these differences and use cases, you can make informed decisions when designing multithreaded applications in Java.

Happy coding!

Comments