ExecutorService e Tipos de Pools de Threads
Crie pools de threads fixos, em cache, unitários e agendados e compreenda quando usar cada um.
ExecutorService e Tipos de Pools de Threads é uma aula grátis de Java Academy no CoddyKit. Esta é a aula 1 de 4. Você pode ler a aula completa abaixo gratuitamente — depois pratica ao vivo no navegador com um editor de código integrado e um tutor de IA 24/7. Faz parte do caminho de aprendizado de Java Academy, e seu progresso é sincronizado entre a web e o app CoddyKit. O curso de Java Academy inclui 4 aulas no total.
Por que usar pools de threads?
Criar uma nova Thread para cada tarefa é caro: a criação e a destruição de threads geram sobrecarga. Um pool de threads reutiliza um conjunto fixo de threads para executar muitas tarefas, reduzindo a sobrecarga e controlando o consumo de recursos.
import java.util.concurrent.*;
// Bad practice: new thread per task
new Thread(() -> System.out.println("task")).start();
// Better: reuse threads from a pool
ExecutorService pool = Executors.newFixedThreadPool(4);
pool.submit(() -> System.out.println("task from pool"));
pool.shutdown();newFixedThreadPool
Cria um pool com exatamente N threads. As tarefas adicionais entram em uma fila até que uma thread fique disponível. É uma boa opção quando você conhece o nível de paralelismo desejado.
ExecutorService pool = Executors.newFixedThreadPool(4);
for (int i = 0; i < 10; i++) {
final int taskId = i;
pool.submit(() -> {
System.out.println("Task " + taskId + " on " + Thread.currentThread().getName());
});
}
pool.shutdown();
pool.awaitTermination(10, TimeUnit.SECONDS);newCachedThreadPool
Cria threads sob demanda e reutiliza as que estão ociosas. Threads ociosas por 60 segundos são encerradas. É uma boa opção para muitas tarefas de curta duração, mas é arriscado para tarefas de longa duração ou ilimitadas, pois pode esgotar a memória.
ExecutorService cached = Executors.newCachedThreadPool();
for (int i = 0; i < 100; i++) {
cached.submit(() -> {
// quick task
double result = Math.sqrt(Math.random());
});
}
cached.shutdown();newSingleThreadExecutor
Um pool com exatamente uma thread. As tarefas são executadas sequencialmente, na ordem de envio. É uma boa opção para serializar o acesso a um recurso compartilhado.
ExecutorService single = Executors.newSingleThreadExecutor();
single.submit(() -> System.out.println("Task 1"));
single.submit(() -> System.out.println("Task 2"));
single.submit(() -> System.out.println("Task 3"));
// Always prints: Task 1, Task 2, Task 3 (sequential)
single.shutdown();newScheduledThreadPool
Oferece suporte a tarefas agendadas e recorrentes. Use-o para consultas periódicas, novas tentativas e manutenção em segundo plano.
ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(2);
// One-shot delay
scheduler.schedule(() -> System.out.println("Delayed!"),
3, TimeUnit.SECONDS);
// Fixed rate (every 2 seconds)
scheduler.scheduleAtFixedRate(
() -> System.out.println("Tick"),
0, 2, TimeUnit.SECONDS);
// Run later: scheduler.shutdown();VirtualThreadExecutor (Java 21+)
O Java 21 introduz threads virtuais, que são leves e baratas de criar. Use Executors.newVirtualThreadPerTaskExecutor() para cargas de trabalho intensivas em E/S:
// Java 21+
try (var exec = Executors.newVirtualThreadPerTaskExecutor()) {
for (int i = 0; i < 10_000; i++) {
final int id = i;
exec.submit(() -> {
Thread.sleep(100); // blocks without tying up OS thread
System.out.println("vthread " + id);
});
}
} // auto-shutdownEscolha do pool adequado
Diretrizes:
- Tarefas limitadas pela CPU: pool fixo com N = número de núcleos da CPU
- Tarefas limitadas por E/S: pool em cache ou threads virtuais
- Tarefas sequenciais: executor de thread única
- Tarefas agendadas/recorrentes: pool de threads agendadas
int cores = Runtime.getRuntime().availableProcessors();
ExecutorService cpuPool = Executors.newFixedThreadPool(cores);
System.out.println("Pool size: " + cores);ThreadPoolExecutor personalizado
Para obter um controle detalhado, crie um ThreadPoolExecutor diretamente:
ThreadPoolExecutor tpe = new ThreadPoolExecutor(
2, // corePoolSize
10, // maximumPoolSize
60L, // keepAliveTime
TimeUnit.SECONDS,
new LinkedBlockingQueue<>(100), // work queue
Executors.defaultThreadFactory(),
new ThreadPoolExecutor.CallerRunsPolicy() // rejection policy
);
tpe.submit(() -> System.out.println("Custom pool task"));
tpe.shutdown();Encerramento adequado
Sempre encerre o ExecutorService para liberar as threads. shutdown() deixa de aceitar novas tarefas, mas conclui as que estão na fila. shutdownNow() tenta cancelar as tarefas em execução.
ExecutorService pool = Executors.newFixedThreadPool(4);
// ... submit tasks ...
pool.shutdown(); // no new tasks
try {
if (!pool.awaitTermination(30, TimeUnit.SECONDS)) {
pool.shutdownNow(); // force cancel
}
} catch (InterruptedException e) {
pool.shutdownNow();
Thread.currentThread().interrupt();
}ExecutorService como AutoCloseable (Java 19+)
No Java 19 e em versões posteriores, ExecutorService implementa AutoCloseable. Use try-with-resources para realizar o encerramento automaticamente:
// Java 19+ (preview), Java 21 stable
try (ExecutorService pool = Executors.newFixedThreadPool(4)) {
pool.submit(() -> System.out.println("task"));
} // pool.close() called: waits for tasks then shuts downPolíticas de rejeição
Quando o pool está saturado, com todas as threads ocupadas e a fila cheia, a política de rejeição trata o excesso:
- AbortPolicy (padrão): lança
RejectedExecutionException - CallerRunsPolicy: a thread chamadora executa a tarefa
- DiscardPolicy: descarta a tarefa silenciosamente
- DiscardOldestPolicy: descarta a tarefa mais antiga da fila
Verificação rápida
Você tem uma tarefa limitada pela CPU que realiza uma computação pesada. Quantas threads o pool fixo deve ter?
Recapitulação: ExecutorService e pools de threads
Principais conclusões:
- Pool fixo: N threads fixas; as tarefas adicionais entram na fila
- Pool em cache: cresce sob demanda; as threads ociosas expiram após 60 segundos
- Thread única: a ordem de execução sequencial é garantida
- Pool agendado: tarefas atrasadas e recorrentes
- Sempre chame
shutdown(); useawaitTermination()para uma saída limpa
Perguntas Frequentes
A aula “ExecutorService e Tipos de Pools de Threads” é grátis?
Sim — o texto completo de “ExecutorService e Tipos de Pools de Threads” é grátis para ler aqui na web. Para praticá-la interativamente (um editor de código integrado e um tutor de IA 24/7) e desbloquear o restante do curso de Java Academy, atualize para CoddyKit PRO. O curso de Java Academy inclui 4 aulas no total.
O que vou aprender em “ExecutorService e Tipos de Pools de Threads”?
Crie pools de threads fixos, em cache, unitários e agendados e compreenda quando usar cada um. Você pratica Java Academy com código prático que executa diretamente no navegador, e um tutor de IA 24/7 responde suas dúvidas enquanto trabalha na aula.
Preciso ter experiência prévia para começar Java Academy?
Nenhuma experiência prévia é necessária. Java Academy no CoddyKit é estruturado para alunos iniciantes até avançados, então você pode começar aqui ou desde o início e aprender no seu ritmo. Esta é a aula 1 de 4.
Quanto tempo leva a aula “ExecutorService e Tipos de Pools de Threads”?
A maioria das aulas CoddyKit leva cerca de 5–10 minutos. Cada uma é compacta e interativa, então você faz progresso constante e retoma exatamente de onde parou entre web e app.
Posso escrever e executar código nesta aula de Java Academy?
Sim. Cada aula de Java Academy inclui um editor de código integrado, então você escreve e executa código real direto no navegador e recebe feedback de IA instantaneamente — nenhuma configuração local necessária.
Todas as aulas deste curso
- ExecutorService e Tipos de Pools de Threads
- Envio de Tarefas: Runnable versus Callable
- Future e Tratamento de Erros
- ScheduledExecutorService para Tarefas Recorrentes