API de Stream Paralelo
Você provavelmente já está familiarizado com a Stream API, seus métodos e como ela funciona (Se não estiver, estude este tópico e depois retorne a este capítulo).
Um fluxo de dados comum não é paralelo, ou seja, por mais conveniente e elegante que seja no código, utilizar a Stream API sem o método parallelStream(), com uma grande quantidade de dados, pode impactar significativamente o desempenho.
Existe também o método parallel() que pode ser utilizado após a conversão para stream.
List<Integer> result = list.stream().parallel()
.map(num -> ++num)
.toList();
A diferença é que parallelStream() cria um fluxo paralelo diretamente a partir da coleção, enquanto parallel() converte um fluxo serial existente em um fluxo paralelo.
E, acima de tudo, nós, como programadores, não precisamos fazer nada além de trocar o método stream() por parallelStream(). A Stream API faz todo o trabalho sozinha e otimiza nosso programa!
Exemplo: Processamento de uma Lista de Números
Suponha que temos uma lista de números e queremos encontrar a soma dos quadrados de todos os números na lista.
Main.java
123456789101112131415161718192021222324252627package com.example; import java.util.Arrays; import java.util.List; public class Main { public static void main(String[] args) { // Create a list of integers List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10); // Sequential stream to sum the squares of numbers int sumSequential = numbers.stream() // Create a sequential stream from the list .mapToInt(n -> n * n) // Map each number to its square .sum(); // Sum the squares // Print the result of the sequential sum System.out.println("Sum of squares (sequential): " + sumSequential); // Parallel stream to sum the squares of numbers int sumParallel = numbers.parallelStream() // Create a parallel stream from the list .mapToInt(n -> n * n) // Map each number to its square .sum(); // Sum the squares // Print the result of the parallel sum System.out.println("Sum of squares (parallel): " + sumParallel); } }
Como pode ser visto, apenas substituímos stream() por parallelStream() E SÓ ISSO. Neste exemplo, não haverá ganho, pois em um ambiente de thread única, um array de 10 caracteres será executado mais rapidamente. Isso ocorre porque a implementação da Stream API realiza diversas ações para distribuir a tarefa entre as threads.
Stream API também decide automaticamente quantas threads utilizará para essa tarefa, buscando ser o mais eficiente possível.
Como Funciona Internamente:
1. Criação de um stream paralelo: Ao chamar parallelStream(), o Java cria um stream paralelo com base na fonte de dados original;
2. Uso do ForkJoinPool (será explorado posteriormente): Streams paralelos utilizam um pool de threads comum, ForkJoinPool.commonPool(), que gerencia um grupo de threads de trabalho;
3. Divisão: Os dados em uma thread paralela são divididos em partes usando a interface Spliterator;
4. Processamento: Cada thread de trabalho no ForkJoinPool processa sua parte dos dados;
5. Junção: Após o processamento dos dados, as threads de trabalho unem os resultados.
Vantagens dos Streams Paralelos
Aumento de desempenho é um dos principais benefícios das threads paralelas, pois permitem a distribuição de tarefas entre múltiplas threads, resultando em processamento mais rápido em processadores multi-core.
Além disso, a facilidade de uso da API de threads paralelas torna simples a integração ao código existente, eliminando a necessidade de gerenciamento complexo de threads.
Adicionalmente, a escalabilidade é uma vantagem significativa, já que as threads paralelas se ajustam automaticamente ao número de núcleos de processador disponíveis, otimizando a execução das tarefas de forma eficiente.
1. Qual classe é utilizada por threads paralelas para controlar threads?
2. Qual método é utilizado para criar um stream paralelo?
3. O que a interface Spliterator faz no contexto de streams paralelos?
Obrigado pelo seu feedback!
Pergunte à IA
Pergunte à IA
Pergunte o que quiser ou experimente uma das perguntas sugeridas para iniciar nosso bate-papo
Awesome!
Completion rate improved to 3.33
API de Stream Paralelo
Deslize para mostrar o menu
Você provavelmente já está familiarizado com a Stream API, seus métodos e como ela funciona (Se não estiver, estude este tópico e depois retorne a este capítulo).
Um fluxo de dados comum não é paralelo, ou seja, por mais conveniente e elegante que seja no código, utilizar a Stream API sem o método parallelStream(), com uma grande quantidade de dados, pode impactar significativamente o desempenho.
Existe também o método parallel() que pode ser utilizado após a conversão para stream.
List<Integer> result = list.stream().parallel()
.map(num -> ++num)
.toList();
A diferença é que parallelStream() cria um fluxo paralelo diretamente a partir da coleção, enquanto parallel() converte um fluxo serial existente em um fluxo paralelo.
E, acima de tudo, nós, como programadores, não precisamos fazer nada além de trocar o método stream() por parallelStream(). A Stream API faz todo o trabalho sozinha e otimiza nosso programa!
Exemplo: Processamento de uma Lista de Números
Suponha que temos uma lista de números e queremos encontrar a soma dos quadrados de todos os números na lista.
Main.java
123456789101112131415161718192021222324252627package com.example; import java.util.Arrays; import java.util.List; public class Main { public static void main(String[] args) { // Create a list of integers List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10); // Sequential stream to sum the squares of numbers int sumSequential = numbers.stream() // Create a sequential stream from the list .mapToInt(n -> n * n) // Map each number to its square .sum(); // Sum the squares // Print the result of the sequential sum System.out.println("Sum of squares (sequential): " + sumSequential); // Parallel stream to sum the squares of numbers int sumParallel = numbers.parallelStream() // Create a parallel stream from the list .mapToInt(n -> n * n) // Map each number to its square .sum(); // Sum the squares // Print the result of the parallel sum System.out.println("Sum of squares (parallel): " + sumParallel); } }
Como pode ser visto, apenas substituímos stream() por parallelStream() E SÓ ISSO. Neste exemplo, não haverá ganho, pois em um ambiente de thread única, um array de 10 caracteres será executado mais rapidamente. Isso ocorre porque a implementação da Stream API realiza diversas ações para distribuir a tarefa entre as threads.
Stream API também decide automaticamente quantas threads utilizará para essa tarefa, buscando ser o mais eficiente possível.
Como Funciona Internamente:
1. Criação de um stream paralelo: Ao chamar parallelStream(), o Java cria um stream paralelo com base na fonte de dados original;
2. Uso do ForkJoinPool (será explorado posteriormente): Streams paralelos utilizam um pool de threads comum, ForkJoinPool.commonPool(), que gerencia um grupo de threads de trabalho;
3. Divisão: Os dados em uma thread paralela são divididos em partes usando a interface Spliterator;
4. Processamento: Cada thread de trabalho no ForkJoinPool processa sua parte dos dados;
5. Junção: Após o processamento dos dados, as threads de trabalho unem os resultados.
Vantagens dos Streams Paralelos
Aumento de desempenho é um dos principais benefícios das threads paralelas, pois permitem a distribuição de tarefas entre múltiplas threads, resultando em processamento mais rápido em processadores multi-core.
Além disso, a facilidade de uso da API de threads paralelas torna simples a integração ao código existente, eliminando a necessidade de gerenciamento complexo de threads.
Adicionalmente, a escalabilidade é uma vantagem significativa, já que as threads paralelas se ajustam automaticamente ao número de núcleos de processador disponíveis, otimizando a execução das tarefas de forma eficiente.
1. Qual classe é utilizada por threads paralelas para controlar threads?
2. Qual método é utilizado para criar um stream paralelo?
3. O que a interface Spliterator faz no contexto de streams paralelos?
Obrigado pelo seu feedback!