Blog

How many ways Thread can be implemented in Java

The Thread class itself implements the Runnable interface, which means any thread in Java is essentially executing a Runnable task. The distinction between using a class that extends Thread and a class that implements Runnable largely comes down to design choices and the specific requirements of your application.

Why Thread Class Exists

The Thread class provides not just a mechanism to execute code on a separate thread but also a suite of methods to manage and monitor the thread’s lifecycle. These include methods for starting, stopping (deprecated for safety reasons), suspending (also deprecated), and joining threads, as well as querying thread state and managing thread priorities.

Use Cases for Extending Thread

Extending the Thread class might be preferable when:

  • You are creating a specialized version of a thread that needs to override other Thread methods in addition to run().
  • Your class is solely dedicated to executing some code in a new thread, and you won’t lose out on the benefits of extending another class due to Java’s single inheritance model.

However, these cases are relatively rare compared to scenarios where implementing Runnable is more advantageous due to its flexibility.

Example Illustrating Both Approaches

Extending Thread

class MyThread extends Thread {
    @Override
    public void run() {
        System.out.println("This code is running in a thread");
    }
}

public class ThreadExample {
    public static void main(String[] args) {
        MyThread myThread = new MyThread();
        myThread.start();
    }
}

Implementing Runnable

class MyRunnable implements Runnable {
    @Override
    public void run() {
        System.out.println("This code is running in a thread");
    }
}

public class RunnableExample {
    public static void main(String[] args) {
        MyRunnable myRunnable = new MyRunnable();
        Thread thread = new Thread(myRunnable);
        thread.start();
    }
}

Why Runnable is Often a Better Choice

Implementing Runnable is generally considered a better practice for several reasons:

  • Composition over Inheritance: It allows your class to extend other classes if needed, preserving the flexibility of your class hierarchy.
  • Separation of Concerns: Implementing Runnable separates the task to be executed in the thread from the thread management itself, adhering to the single responsibility principle.
  • Reuse and Flexibility: You can pass the same Runnable instance to multiple Thread objects or use it with other concurrency utilities like ExecutorService, making your code more reusable and adaptable.

The decision to extend Thread directly might make sense in specific contexts, but these scenarios are less common. The design benefits of implementing Runnable usually outweigh the simplicity of extending Thread, which is why Runnable is often recommended for new Java code that involves threading.

Avatar

Neelabh

About Author

As Neelabh Singh, I am a Senior Software Engineer with 6.6 years of experience, specializing in Java technologies, Microservices, AWS, Algorithms, and Data Structures. I am also a technology blogger and an active participant in several online coding communities.

You may also like

Blog Design Pattern

Understanding the Builder Design Pattern in Java | Creational Design Patterns | CodeTechSummit

Overview The Builder design pattern is a creational pattern used to construct a complex object step by step. It separates
Blog Tech Toolkit

Base64 Decode

Base64 encoding is a technique used to encode binary data into ASCII characters, making it easier to transmit data over