Thread vs Runnable in Java
Thread and Runnable are the two building blocks for creating threads. Thread is a class that represents a thread of execution and knows how to start it. Runnable is a functional interface with one method, run(), that represents a task: the work to be done. You can either extend Thread and put the work inside it, or write the work as a Runnable and give it to a Thread. In this lesson, you will learn the differences and why Runnable is the better choice.
Example: The Same Task Both Ways
Let's see an example that greets three students both ways.
public class Compare {
static class GreetThread extends Thread {
private final String name;
GreetThread(String name) { this.name = name; }
@Override
public void run() {
System.out.println("Thread subclass greets " + name);
}
}
static class GreetTask implements Runnable {
private final String name;
GreetTask(String name) { this.name = name; }
@Override
public void run() {
System.out.println("Runnable task greets " + name);
}
}
public static void main(String[] args) throws InterruptedException {
Thread a = new GreetThread("Navika");
a.start();
a.join();
Runnable task = new GreetTask("Srihitha");
Thread b = new Thread(task);
b.start();
b.join();
task.run();
Thread c = new Thread(
() -> System.out.println("Lambda greets Advitha"));
c.start();
c.join();
}
}Thread subclass greets Navika
Runnable task greets Srihitha
Runnable task greets Srihitha
Lambda greets AdvithaExplanation: Both styles do the same job. The difference is in the design: the Runnable task is separate from the thread, so the same task object can be given to a thread, called directly (task.run() ran it in the main thread), or submitted to a thread pool. The lambda is just a short Runnable.
Differences Between Thread and Runnable
Extending Thread | Implementing Runnable | |
|---|---|---|
| Type | A class | A functional interface |
| Inheritance | Uses up your one superclass | Your class can still extend another |
| Separation | Task and thread are mixed together | Task is separate from the thread that runs it |
| Reuse | One object per thread run | One task can be run by many threads or a pool |
| Lambdas | Not possible | () -> ... works |
| Executors | Not designed for them | Submit directly to an ExecutorService |
| Thread methods | Inherited (getName, interrupt...) | Use Thread.currentThread() |
When a Task Returns a Result
Common Mistakes
Extending Thread when you only need a task. It blocks other inheritance and mixes concerns.
Thinking Runnable creates a thread. It's only the task; a Thread or executor must run it.
Interview Corner
Which is better: extending Thread or implementing Runnable?
Implementing Runnable is generally better. It keeps the task separate from the threading mechanism, leaves the class free to extend another class, allows the same task to be run by different threads or submitted to an ExecutorService, and can be written as a lambda. Extending Thread is only appropriate when you really need to customize thread behavior itself.
Practice
- Easy: Rewrite a class that extends
Threadas aRunnablelambda. - Harder: Create one
Runnablethat prints the current thread's name, and run it with three differently named threads.
Key Takeaways
Was this tutorial helpful?