0Pricing
Java Academy · Aula

Quando o paralelismo ajuda

Fatores como carga de trabalho e tamanho dos dados.

Quando o paralelismo ajuda é uma aula grátis de Java Academy no CoddyKit. Esta é a aula 2 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.

O paralelismo tem um custo

Executar em paralelo adiciona custos: dividir os dados, distribuir tarefas e combinar resultados. Isso só compensa quando esse custo é menor que o tempo economizado.

import java.util.stream.IntStream;

public class Main {
    public static void main(String[] args) {
        long sum = IntStream.rangeClosed(1, 10_000_000)
            .parallel()
            .asLongStream()
            .sum();
        System.out.println(sum);
    }
}

Fator 1: tamanho dos dados (N)

Um N grande dilui o custo fixo do paralelismo. Uma regra prática aproximada é que sejam necessários dezenas de milhares de elementos para que o processamento paralelo valha a pena.

import java.util.stream.IntStream;

public class Main {
    public static void main(String[] args) {
        long count = IntStream.rangeClosed(1, 5_000_000)
            .parallel()
            .filter(n -> n % 7 == 0)
            .count();
        System.out.println(count);
    }
}

Fator 2: trabalho por elemento (Q)

O custo Q de processar cada elemento é importante. Um trabalho caro por elemento, com cálculos intensos, se beneficia do paralelismo mesmo com um N menor.

import java.util.stream.IntStream;

public class Main {
    public static void main(String[] args) {
        long primes = IntStream.rangeClosed(2, 200_000)
            .parallel()
            .filter(Main::isPrime)
            .count();
        System.out.println(primes);
    }

    static boolean isPrime(int n) {
        for (int i = 2; (long) i * i <= n; i++)
            if (n % i == 0) return false;
        return true;
    }
}

A intuição de N vezes Q

Considere o trabalho útil total como N x Q. Quanto maior esse produto, mais o paralelismo pode ajudar. Um N pequeno ou um Q trivial raramente o justifica.

import java.util.stream.IntStream;

public class Main {
    public static void main(String[] args) {
        double sum = IntStream.rangeClosed(1, 1_000_000)
            .parallel()
            .mapToDouble(n -> Math.sqrt(n) * Math.log(n + 1))
            .sum();
        System.out.println(sum);
    }
}

Fator 3: divisibilidade

Fontes de dados que podem ser divididas de forma barata e uniforme são boas para o processamento paralelo: vetores, ArrayList e IntStream.range. LinkedList e fontes baseadas em iteradores são difíceis de dividir.

import java.util.ArrayList;
import java.util.List;

public class Main {
    public static void main(String[] args) {
        List<Integer> list = new ArrayList<>();
        for (int i = 0; i < 1_000_000; i++) list.add(i);
        long even = list.parallelStream().filter(n -> n % 2 == 0).count();
        System.out.println(even);
    }
}

Boa fonte: vetores e intervalos

Intervalos de tipos primitivos têm tamanho conhecido e podem ser divididos em O(1), o que os torna fontes paralelas ideais.

import java.util.stream.LongStream;

public class Main {
    public static void main(String[] args) {
        long sum = LongStream.rangeClosed(1, 20_000_000)
            .parallel()
            .sum();
        System.out.println(sum);
    }
}

Fonte ruim: geradores iterativos

Stream.iterate produz elementos sequencialmente por definição, portanto não pode ser dividido até que os elementos sejam materializados. É uma fonte paralela fraca.

import java.util.stream.Stream;

public class Main {
    public static void main(String[] args) {
        long count = Stream.iterate(1, n -> n + 1)
            .limit(1_000_000)
            .parallel()
            .filter(n -> n % 2 == 0)
            .count();
        System.out.println(count);
    }
}

Fator 4: etapa de combinação de baixo custo

O paralelismo precisa de uma forma barata de combinar resultados parciais. sum e count são combinados de maneira trivial; construir uma lista ordenada ou usar um coletor com muitas estruturas de árvore exige uma combinação cara.

import java.util.stream.IntStream;

public class Main {
    public static void main(String[] args) {
        int max = IntStream.rangeClosed(1, 5_000_000)
            .parallel()
            .map(n -> n % 1000)
            .max()
            .getAsInt();
        System.out.println(max);
    }
}

Evite em trabalhos limitados por E/S

Os fluxos paralelos têm como alvo tarefas limitadas pela CPU no conjunto de divisão e junção. E/S bloqueante esgota o conjunto compartilhado e prejudica todo o aplicativo. Em vez disso, use executores dedicados para E/S.

import java.util.stream.IntStream;

public class Main {
    public static void main(String[] args) {
        long total = IntStream.rangeClosed(1, 1_000_000)
            .parallel()
            .mapToLong(n -> (long) n * n)
            .sum();
        System.out.println(total);
    }
}

Meça, não adivinhe

A única forma confiável de saber se o paralelismo ajuda é fazer um teste de desempenho com dados realistas. A intuição sobre desempenho frequentemente está errada.

import java.util.stream.LongStream;

public class Main {
    public static void main(String[] args) {
        long start = System.nanoTime();
        long sum = LongStream.rangeClosed(1, 50_000_000).parallel().sum();
        long ms = (System.nanoTime() - start) / 1_000_000;
        System.out.println("sum=" + sum + " took ~" + ms + "ms");
    }
}

Uma lista de verificação prática

Prefira o processamento paralelo quando todos estes itens forem atendidos:

  • N grande e/ou trabalho caro por elemento.
  • Uma fonte divisível (vetor, ArrayList, intervalo).
  • Uma combinação associativa e barata.
  • Trabalho limitado pela CPU, sem E/S bloqueante.
import java.util.stream.IntStream;

public class Main {
    public static void main(String[] args) {
        double avg = IntStream.rangeClosed(1, 10_000_000)
            .parallel()
            .mapToDouble(Math::sqrt)
            .average()
            .getAsDouble();
        System.out.println(avg);
    }
}

Verificação rápida

Qual cenário é o melhor candidato para um fluxo paralelo?

Recapitulação

Você aprendeu quando o paralelismo ajuda:

  • O benefício cresce com N x Q (tamanho dos dados vezes o custo por elemento).
  • É necessária uma fonte divisível (vetores, ArrayList, intervalos).
  • É necessária uma combinação associativa e barata.
  • Mantenha o trabalho limitado pela CPU, evite E/S bloqueante e sempre faça medições.

Perguntas Frequentes

A aula “Quando o paralelismo ajuda” é grátis?

Sim — o texto completo de “Quando o paralelismo ajuda” é 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 “Quando o paralelismo ajuda”?

Fatores como carga de trabalho e tamanho dos dados. 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 2 de 4.

Quanto tempo leva a aula “Quando o paralelismo ajuda”?

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

  1. Criando streams paralelos
  2. Quando o paralelismo ajuda
  3. Segurança de threads e efeitos colaterais
  4. Armadilhas comuns
← Voltar para Java Academy