Both are ways to define work that runs on a separate thread, but they differ in design and flexibility.
class MyThread : Thread() {
override fun run() {
println("Running on: ${currentThread().name}")
}
}
// Usage
val thread = MyThread()
thread.start()
class MyRunnable : Runnable {
override fun run() {
println("Running on: ${Thread.currentThread().name}")
}
}
// Usage
val thread = Thread(MyRunnable())
thread.start()
// Or with lambda
Thread { println("Lambda runnable") }.start()
| Aspect | Thread | Runnable |
|---|---|---|
| Type | Class (extends) | Interface (implements) |
| Inheritance | Can't extend another class | Can extend another class |
| Reusability | Less reusable | More reusable |
| Resource sharing | Each thread = separate object | Same Runnable, multiple threads |
| Thread pool compatible | No | Yes (Executor.execute(runnable)) |
1. Better OOP Design
class MyActivity : Activity(), Runnable {
// Can implement Runnable AND extend Activity
override fun run() { /* background work */ }
}
2. Separation of Concerns
3. Thread Pool Compatibility
val runnable = Runnable { /* work */ }
executorService.execute(runnable) // Works!
executorService.execute(thread) // Doesn't make sense
4. Resource Efficiency
val task = Runnable { /* work */ }
// Reuse same task logic with multiple threads
repeat(5) { Thread(task).start() }
interface Callable<V> {
fun call(): V // Can return a result and throw exceptions
}
val callable = Callable { "Result" }
val future = executor.submit(callable)
val result = future.get() // "Result"
In modern Android development:
Mark this when you can explain the answer in your own words.
Help fellow developers prepare for interviews
Sharing helps the Android community grow ๐