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:

Jan 16, 2025 - 22:03
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:

Image description