Ответ
Thread принимает Runnable, потому что это гибкий подход — можно передать любую логику выполнения в виде объекта, реализующего run(). Это лучше наследования (если бы Thread был абстрактным классом), так как Java не поддерживает множественное наследование.
Пример:
Thread thread = new Thread(() -> System.out.println("Running"));
thread.start();
Здесь Runnable — это лямбда, но можно и через класс:
class MyTask implements Runnable {
@Override
public void run() { /* логика */ }
}
Thread thread = new Thread(new MyTask());
Также Runnable можно переиспользовать или передавать в ExecutorService.