Runnable Preferred Over Thread Extension
Fast recall
Quick revision
Core answer
Runnable describes a task separately from how it is scheduled. The same task can be run by a Thread, an executor, or another framework, and the class remains free to extend a meaningful superclass. Extending Thread is valid when customizing the thread object itself, but it mixes the task with its execution mechanism. A Thread also implements Runnable; do not say it cannot be submitted, although submitting a Thread calls its run() as a task and does not start that Thread object.Understanding of object-oriented design principles and thread management best practices in production Java applications
Simply stating 'Runnable is better' without explaining the single inheritance limitation or the task-thread separation principle
Mention that ExecutorService cannot accept Thread subclasses directly, demonstrating awareness of modern concurrent programming patterns
Interview-ready guide
Interview answer
Implementing Runnable is preferred over extending Thread for three reasons.
First, Java doesn't support multiple inheritance. If you extend Thread, you can't extend any other class, which limits your design. In real apps you often need to extend a base service or a framework component.
Second, Runnable separates the task from how it runs. You define what to do, not how to run it. So you can reuse the same task with a raw thread, a thread pool, or a scheduled executor.
Third, and this is the one that stands out, an ExecutorService can't accept Thread subclasses. Its execute and submit methods only take Runnable or Callable. So extending Thread locks you out of modern concurrency utilities like thread pools.
Most Spring Boot apps run background work, like sending emails or processing uploads, through an ExecutorService with Runnable tasks. It's cleaner and more flexible. The only time you'd extend Thread is to customize the thread's own behavior, like overriding start, which is rare outside framework internals.
Runnable Preferred Over Thread Extension
Direct Answer
A Runnable describes a task separately from how it is scheduled. The same task can be run by a Thread, an executor, or another framework, and the class remains free to extend a meaningful superclass. Extending Thread is valid when customizing the thread object itself, but it mixes the task with its execution mechanism. A Thread also implements Runnable; do not say it cannot be submitted, although submitting a Thread calls its run() as a task and does not start that Thread object.
Common Mistakes & Pitfalls
- Saying an executor rejects Thread subclasses:
ThreadimplementsRunnable, so it is accepted; the executor callsrun()as a task rather thanstart(). - Claiming the two forms have different thread weight: the execution mechanism determines the thread, not whether the task class extends Thread.
- Calling
run()and expecting concurrency: a direct call runs on the current thread;start()creates the new Thread execution. - Extending Thread for ordinary work: this couples the job to its runner and prevents extending another class.
- Assuming Runnable always means a pool: it only describes the task; a Thread, executor, or direct call can run it.
Check your understanding
Answer these without looking back at the article.
- Can you submit a Thread subclass to an ExecutorService?
- What is the single responsibility principle and how does it apply here?
- Is there any situation where extending Thread makes more sense?
Looking for a structured roadmap?
Every module on this page is also part of the full Java backend interview track.