Los Parallel Streams en Java son una extensión de la API de Streams introducida en Java 8 que permiten procesar colecciones de datos en paralelo, aprovechando múltiples núcleos del procesador.
Son útiles para operaciones intensivas en grandes volúmenes de datos, pero requieren cuidado porque no siempre ofrecen mejoras de rendimiento.
Dividen el trabajo en múltiples tareas que se ejecutan en paralelo usando el ForkJoinPool común de Java.
Su objetivo es mejorar el rendimiento en operaciones sobre grandes colecciones, especialmente cuando las operaciones son independientes y no dependen del orden.
Veamos el siguiente ejemplo con listas.
ParallelStreamTest.java
package main; import java.util.List; import java.util.Arrays; public class ParallelStreamTest{ public static void main(String[] args){ List<Integer> numeros = Arrays.asList(1,2,3,4,5,6,7,8,9,10); numeros.parallelStream() .filter(n -> n % 2 == 0) .forEach(System.out::println); } }
Este código filtra números pares y los procesa en paralelo
Compilamos:
$ javac ParallelStreamTest.java
Ejecutamos:
$ java ParallelStreamTest
Salida:
6 10 8 4 2
¿Cómo funcionan?
- Internamente usan el Fork/Join Framework, que divide la colección en sub-tareas.
- Cada sub-tarea se ejecuta en un hilo distinto del common pool.
- Los resultados se combinan al final.
Entre las ventajas encontramos que aprovechan múltiples núcleos, dando mejor rendimiento en operaciones pesadas. No necesitas gestionar hilos manualmente y se integran directamernte con la API de Streams.
Entre las desventajas encontramos que no siempre son más rápidos para colecciones pequeñas, el overhead de dividir/combinar puede ser mayor que el beneficio. No tiene un orden garantizado, así que el resultado puede llegar en orden distinto al original. Además de presentar ciertos problemas de concurrencia si las operaciones no son thread-safe, pueden aparecer errores.
Si tu aplicación ya usa intensivamente el ForkJoinPool, los Parallel Streams pueden competir por recursos.
Veamos otro ejemplo. Compararemos un rendimiento secuencial contra uno en paralelo.
ParallelStreamTestTwo.java
package main; import java.util.List; import java.util.Arrays; import java.util.stream.IntStream; public class ParallelStreamTestTwo{ public static void main(String[] args){ List<Integer> lista = IntStream.rangeClosed(1, 1_000_000).boxed().toList(); // Secuencial long inicio = System.currentTimeMillis(); lista.stream().reduce(0, Integer::sum); long fin = System.currentTimeMillis(); System.out.println("Secuencial: " + (fin - inicio) + " ms"); // Paralelo inicio = System.currentTimeMillis(); lista.parallelStream().reduce(0, Integer::sum); fin = System.currentTimeMillis(); System.out.println("Paralelo: " + (fin - inicio) + " ms"); } }
Compilamos:
$ javac ParallelStreamTestTwo.java
Ejecutamos:
$ java ParallelStreamTestTwo
Salida:
Secuencial: 108 ms Paralelo: 69 ms
Como se puede ver, el rendimiento en paralelo fue mejor que el secuencial.
Los Parallel Streams son una herramienta poderosa en Java para aprovechar múltiples núcleos, pero deben usarse con criterio.
Enlaces:
https://www.arquitecturajava.com/java-parallel-stream-y-rendimiento/https://www.oracle.com/latam/technical-resources/articles/java/processing-streams-java-se8.html

Comentarios
Publicar un comentario