Prática de multithreading de verdade: enviamos tarefas para o
ExecutorService em vez de criar
Thread manualmente, gerenciamos o pool, a fila e o ciclo de vida (
shutdown(),
shutdownNow()). Analisamos a diferença entre
Runnable e
Callable<T>, obtemos resultados via
Future e seus métodos (
get(),
isDone(),
cancel(...),
isCancelled()). Mostraremos a execução de várias tarefas,
invokeAll/
invokeAny, o tratamento de
ExecutionException e erros comuns.