Si amplía Thread, siempre tiene que llamar a .start(), que inicia un thread NUEVO y ejecuta la tarea.
Si lo hace Runnable, también puede hacer un nuevo Thread (ejecutable) .start(), pero no se limita a eso. Usted puede reciclar hilos, con el consiguiente ahorro de algunos recursos como esto:
ExecutorService recycleSingleThread = Executors.newSingleThreadExecutor();
service.execute(runnable);
service.execute(someOtherTask);
Deja un montón de sus runnables en una lista primero y luego ejecutarlos cuando sientes que la ejecución de ellos:
List<Runnable> todoList = new ArrayList<Runnable>();
Runnable fetchPaper = new Runnable("paper");
todoList.add(fetchPaper);
Runnable fetchMilk = new Runnable("milk");
todoList.add(fetchMilk);
//do something else or even return todoList...
ExecutorService recycleSingleThread = Executors.newSingleThreadExecutor();
for(Runnable task : todoList){
recycleSingleThread.execute(task);
}
O puede incluso hacer
runnable.run();
dentro de su propio hilo.
Tal vez incluso podría guardar un ejecutable, quitar la serialización y ejecutarlo.
Toda esta flexibilidad no estará presente si amplía Thread.