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
- Criando streams paralelos
- Quando o paralelismo ajuda
- Segurança de threads e efeitos colaterais
- Armadilhas comuns