Runnable vs Thread in Java
Learn Runnable vs Thread in Java: why Runnable decouples tasks from execution, when to use executors, and how start() differs from run(). With clear examples.
Expected Interview Answer
Runnable is an interface that defines a task's run() logic, while Thread is a class that actually runs a task on a separate call stack; you implement Runnable to describe work and hand it to a Thread (or executor) to execute it.
Extending Thread ties your task to a specific execution mechanism and uses up your one allowed superclass, whereas implementing Runnable separates the work from how it runs, so the same task can be reused across raw threads, thread pools, or executors. Modern Java almost always favors Runnable (or Callable) submitted to an ExecutorService rather than subclassing Thread directly.
- Separates the task from the execution mechanism
- Leaves your single inheritance slot free for a real base class
- Reusable across raw threads, pools, and executors
- Easier to unit test because run() is just a method
- Encouraged by the java.util.concurrent framework
AI Mentor Explanation
A Runnable is like a written batting plan handed to whoever is next in — it just says what to do. A Thread is the actual batter walking to the crease and playing. One plan can be given to any batter, but the batter is the one who physically faces the deliveries.
Step-by-Step Explanation
Step 1
Define the task
Implement the Runnable interface and put your work inside the run() method, which takes no arguments and returns void.
Step 2
Wrap or submit it
Pass the Runnable to a Thread constructor, or better, submit it to an ExecutorService that manages a pool of worker threads.
Step 3
Start execution
Call thread.start() (not run()) so the JVM creates a new call stack; calling run() directly executes on the current thread with no concurrency.
Step 4
Coordinate results
Because run() returns nothing, use shared state, a Callable/Future, or a CompletableFuture when the task must produce a value.
Step 5
Prefer pooling
Reuse threads via executors instead of creating a new Thread per task to avoid the cost and unbounded growth of manual thread creation.
What Interviewer Expects
- Runnable is an interface, Thread is a class
- Why composition (Runnable) beats inheritance (extends Thread)
- Single-inheritance limitation of extending Thread
- Difference between start() and run()
- Knowledge that executors and Callable are the modern approach
Common Mistakes
- Calling run() instead of start(), so no new thread is created
- Saying Runnable creates a thread by itself
- Extending Thread by default and losing the superclass slot
- Confusing Runnable with Callable (Runnable returns void)
- Thinking you must subclass Thread to run concurrent code
Best Answer (HR Friendly)
“Runnable is just a description of a job you want done, while a Thread is the worker that actually does it. In Java we usually write the job as a Runnable so any worker or worker pool can pick it up, instead of building a special worker for each job.”
Code Example
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class TaskDemo {
public static void main(String[] args) {
// Preferred: task as a Runnable, execution handled by a pool
Runnable task = () -> System.out.println("Running on " + Thread.currentThread().getName());
// Option 1: hand the Runnable to a raw Thread
Thread t = new Thread(task);
t.start(); // start() creates a new call stack; run() would not
// Option 2 (recommended): submit to an ExecutorService
ExecutorService pool = Executors.newFixedThreadPool(2);
pool.submit(task);
pool.shutdown();
}
}
// Discouraged: coupling task to Thread via inheritance
class Worker extends Thread {
@Override
public void run() {
System.out.println("Cannot extend any other class now");
}
}Follow-up Questions
- What is the difference between Runnable and Callable?
- Why should you call start() instead of run()?
- What problems do thread pools solve over new Thread() per task?
- How does the single-inheritance rule affect extending Thread?
- What is the role of ExecutorService and Future?
MCQ Practice
1. Which statement is true about Runnable and Thread?
Runnable is a functional interface defining run(); Thread is a concrete class that can execute a Runnable.
2. What happens if you call run() directly on a Thread object?
Calling run() invokes it like an ordinary method on the current thread; only start() creates a new thread of execution.
3. Why is implementing Runnable often preferred over extending Thread?
Runnable separates what the task does from how it runs and leaves your class free to extend another class.
Flash Cards
Is Runnable a class or an interface? — A functional interface with a single run() method that returns void.
start() vs run()? — start() spawns a new thread and then calls run() on it; calling run() directly stays on the current thread.
Why prefer Runnable over extending Thread? — It decouples the task from execution and preserves your one allowed superclass.
Runnable vs Callable? — Runnable.run() returns void and cannot throw checked exceptions; Callable.call() returns a value and can throw.