🎓 Top 15 Udemy Courses (80-90% Discount): My Udemy Courses - Ramesh Fadatare — All my Udemy courses are real-time and project oriented courses.
▶️ Subscribe to My YouTube Channel (178K+ subscribers): Java Guides on YouTube
▶️ For AI, ChatGPT, Web, Tech, and Generative AI, subscribe to another channel: Ramesh Fadatare on YouTube
In Java, multithreading is one of the core features that allows programs to perform multiple tasks simultaneously. When learning how to create threads, you’ll encounter two commonly used approaches:
- Extending the
Threadclass - Implementing the
Runnableinterface
Both are used to define and execute tasks in separate threads, but they are not the same and serve different design purposes.
In this article, we will explain the difference between Runnable and Thread in Java, their advantages and disadvantages, and when to use one over the other — with examples and a clear comparison table.
Introduction to Threading in Java
Multithreading in Java allows multiple parts of a program to execute concurrently, making applications more responsive and efficient — especially for tasks like I/O operations, file processing, or background services.
Java provides two main ways to create threads:
- By extending the
Threadclass - By implementing the
Runnableinterface
Let’s look at both.
What is Thread in Java?
Thread is a class in the java.lang package that represents a single thread of execution. You can create a thread by extending this class and overriding the run() method.
Example: Using Thread Class
class MyThread extends Thread {
public void run() {
System.out.println("Thread is running: " + Thread.currentThread().getName());
}
}
public class ThreadExample {
public static void main(String[] args) {
MyThread t1 = new MyThread();
t1.start(); // Starts a new thread
}
}Output:
Thread is running: Thread-0Key Points:
- You extend the
Threadclass. - You override the
run()method to define the thread’s task. - You call
start()to begin the thread’s execution.
What is Runnable in Java?
Runnable is a functional interface in Java that represents a task that can be executed by a thread. Instead of extending Thread, you implement Runnable and pass the object to a Thread instance.
Example: Using Runnable Interface
class MyTask implements Runnable {
public void run() {
System.out.println("Runnable is running: " + Thread.currentThread().getName());
}
}
public class RunnableExample {
public static void main(String[] args) {
Runnable task = new MyTask();
Thread t1 = new Thread(task);
t1.start(); // Starts a new thread
}
}Output:
Runnable is running: Thread-0Key Points:
- You implement the
Runnableinterface. - The thread logic goes inside the
run()method. - A new
Threadobject is created using theRunnableobject.
📊 Comparison: Runnable vs Thread

Why Prefer Runnable Over Thread?
✅ 1. Java Supports Single Inheritance
Java doesn’t support multiple inheritance. If your class extends Thread, it cannot extend any other class. But if your class implements Runnable, it’s free to extend another class too.
class Base {}
class Task extends Base implements Runnable {
public void run() {
System.out.println("Running task...");
}
}This adds more flexibility and reusability.
✅ 2. Separation of Concerns
When you use Runnable, the task (business logic) is separated from the thread (execution mechanism). This is a cleaner design because:
- You can reuse the task with different threads.
- You can execute the same task in different ways (e.g., in a thread pool).
✅ 3. Thread Pool Compatibility
Java’s Executor Framework (introduced in Java 5) works with Runnable, not Thread.
ExecutorService executor = Executors.newFixedThreadPool(2);
executor.submit(new MyTask()); // MyTask implements RunnableThis is a scalable and efficient way to manage threads — a feature not available with custom Thread subclasses.
Running Multiple Threads
Let’s see how both approaches run multiple threads:
✅ Using Thread:
class MyThread extends Thread {
public void run() {
System.out.println("Thread running: " + Thread.currentThread().getName());
}
}
public class TestThread {
public static void main(String[] args) {
new MyThread().start();
new MyThread().start();
}
}✅ Using Runnable:
class MyRunnable implements Runnable {
public void run() {
System.out.println("Runnable running: " + Thread.currentThread().getName());
}
}
public class TestRunnable {
public static void main(String[] args) {
Runnable r = new MyRunnable();
new Thread(r).start();
new Thread(r).start();
}
}Both methods produce similar output, but the Runnable approach is more scalable and modular.
❌ Common Mistakes to Avoid
1. Calling run() Instead of start()
Thread t = new Thread(() -> System.out.println("Wrong"));
t.run(); // ❌ Executes in main thread (no multithreading)✅ Always use start() to run in a separate thread.
2. Forgetting to Implement run() in Runnable
class Task implements Runnable {
// Missing run() method – won't compile!
}✅ Always override the run() method.
🔁 Summary Table

✅ Final Thoughts
While both Thread and Runnable can be used to create and run threads in Java, they serve different purposes:
- Use
Threadwhen you have a quick, small task and no need to extend another class. - Use
Runnablewhen you want cleaner code, better reusability, and compatibility with executors and thread pools.
Best Practice:
Always prefer implementingRunnableover extendingThreadin real-world applications.
It gives your code more flexibility, aligns with modern Java concurrency features, and promotes better object-oriented design.
Comments
Post a Comment
Leave Comment