Item 84: Não dependa do agendador de threads
1. O papel do agendador de threads Função: Determina quais threads executáveis devem rodar e por quanto tempo. Variedade: Políticas variam entre sistemas operacionais. Recomendação: Não dependa do comportamento do agendador para correção ou desempenho; isso compromete a portabilidade. 2. Estratégia para programas robustos Manter threads executáveis equilibradas: O número médio de threads executáveis deve ser próximo ao número de processadores disponíveis. Evita sobrecarga no agendador e garante comportamento consistente. Threads não executáveis: O número total de threads pode ser maior, mas as threads em espera (não executáveis) não afetam a carga. 3. Técnicas para gerenciar threads Evitar espera-ativa: Threads não devem verificar constantemente o estado de um objeto compartilhado. Isso aumenta o uso do processador e prejudica a eficiência. Diminuir o número de threads executáveis: Dimensionar corretamente pools de threads no Executor Framework. Criar tarefas pequenas, mas não tão pequenas que a sobrecarga prejudique o desempenho. 4. Exemplo de má prática: espera-ativa public class SlowCountDownLatch { private int count; public SlowCountDownLatch(int count) { this.count = count; } public void await() { while (count > 0) { // Espera-ativa: utiliza o processador desnecessariamente } } public void countDown() { if (count > 0) { count--; } } } Problema: Consome recursos excessivos, deixando o processador ocupado inutilmente. Alternativa: Utilize CountDownLatch, que usa bloqueio eficiente. 5. Evitar o uso de Thread.yield Não confiável: Funciona de forma inconsistente em diferentes implementações da JVM. Não resolve problemas de forma robusta ou portátil. Exemplo incorreto: while (!condition) { Thread.yield(); // Tentativa de "ceder" a CPU para outras threads } Solução: Reestruturar o código para reduzir threads executáveis. 6. Ajuste de prioridades de threads Pouco portátil: Prioridades de threads variam entre sistemas operacionais e JVMs. Uso recomendado: Melhorar qualidade de serviço em aplicações funcionais. Evitar para corrigir problemas estruturais. 7. Conclusões Não dependa do agendador para: Correção do programa. Otimização de desempenho. Evite: Uso de Thread.yield. Ajustes excessivos de prioridade de threads. Melhor abordagem: Reestruturar aplicações para manter um número equilibrado de threads executáveis. Exemplo do livro:
1. O papel do agendador de threads
- Função: Determina quais threads executáveis devem rodar e por quanto tempo.
- Variedade: Políticas variam entre sistemas operacionais.
- Recomendação: Não dependa do comportamento do agendador para correção ou desempenho; isso compromete a portabilidade.
2. Estratégia para programas robustos
Manter threads executáveis equilibradas:
- O número médio de threads executáveis deve ser próximo ao número de processadores disponíveis.
- Evita sobrecarga no agendador e garante comportamento consistente.
Threads não executáveis:
O número total de threads pode ser maior, mas as threads em espera (não executáveis) não afetam a carga.
3. Técnicas para gerenciar threads
Evitar espera-ativa:
- Threads não devem verificar constantemente o estado de um objeto compartilhado.
- Isso aumenta o uso do processador e prejudica a eficiência.
Diminuir o número de threads executáveis:
Dimensionar corretamente pools de threads no Executor Framework.
Criar tarefas pequenas, mas não tão pequenas que a sobrecarga prejudique o desempenho.
4. Exemplo de má prática: espera-ativa
public class SlowCountDownLatch {
private int count;
public SlowCountDownLatch(int count) {
this.count = count;
}
public void await() {
while (count > 0) {
// Espera-ativa: utiliza o processador desnecessariamente
}
}
public void countDown() {
if (count > 0) {
count--;
}
}
}
Problema: Consome recursos excessivos, deixando o processador ocupado inutilmente.
Alternativa: Utilize CountDownLatch, que usa bloqueio eficiente.
5. Evitar o uso de Thread.yield
Não confiável:
- Funciona de forma inconsistente em diferentes implementações da JVM.
- Não resolve problemas de forma robusta ou portátil.
Exemplo incorreto:
while (!condition) {
Thread.yield(); // Tentativa de "ceder" a CPU para outras threads
}
Solução: Reestruturar o código para reduzir threads executáveis.
6. Ajuste de prioridades de threads
Pouco portátil:
- Prioridades de threads variam entre sistemas operacionais e JVMs. Uso recomendado:
- Melhorar qualidade de serviço em aplicações funcionais. Evitar para corrigir problemas estruturais.
7. Conclusões
- Não dependa do agendador para:
- Correção do programa.
- Otimização de desempenho.
Evite:
- Uso de Thread.yield.
- Ajustes excessivos de prioridade de threads.
Melhor abordagem:
- Reestruturar aplicações para manter um número equilibrado de threads executáveis.
Exemplo do livro: