What are the differences between implementing Runnable and extending Thread in Java?

Implementing Runnable and extending Thread are two approaches for creating concurrent tasks in Java. While both can execute code in a separate thread, implementing Runnable is generally considered the better design choice because it separates the task logic from thread management and provides greater flexibility.

Key Points: • A class implementing Runnable can still extend another class, whereas a class extending Thread cannot due to Java's single inheritance rule. • Runnable promotes better object-oriented design by separating the task from the thread responsible for executing it. • Multiple Thread objects can execute the same Runnable instance, making code more reusable and maintainable.

Example: In an e-commerce application, an OrderProcessor task can implement Runnable. Multiple threads can then execute different order-processing tasks without tightly coupling business logic to the Thread class.

Code Example:

class Task implements Runnable {

    @Override
    public void run() {

System.out.println("Task executed by: " +

                Thread.currentThread().getName());
    }
}

public class Main {

    public static void main(String[] args) {

        Task task = new Task();

        Thread t1 = new Thread(task);
        Thread t2 = new Thread(task);

        t1.start();
        t2.start();
    }
}

Interview Tip: A concise interview answer is: Both approaches create concurrent execution, but implementing Runnable is preferred because it separates business logic from thread management, supports code reuse, and avoids the limitations of Java's single inheritance. Extending Thread is suitable only for simple scenarios where customizing thread behavior is required.