El concepto de Java Parallel Stream es un concepto sencillo de entender . En muchas ocasiones podemos tener un flujo de trabajo que necesitemos mejorar su rendimiento permitiendo su ejecución en paralelo a través de varios Threads . Esto es algo que dependiendo del código del programa hacerlo sin utilizar streams es complicado. Vamos a ver un ejemplo.
package com.arquitecturajava.streams.ejemplo013Paralelos; public class Principal2 { public static void main(String[] args) { int total=0; long numero1=System.currentTimeMillis(); for (int i=0;i<10;i++) { total+=duplicar(i); } long numero2=System.currentTimeMillis(); System.out.println(numero2-numero1); System.out.println(total); } public static int duplicar( int numero) { try { Thread.sleep(1000); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } return numero*2; } }
Acabamos de construir un sencillo bucle for en el cual invocamos al método duplicar. Lo curioso de este método es que pone el thread a dormir durante un segundo.
Por lo tanto si realizamos 10 iteraciones el bucle tardará unos 10 segundos en ejecutarse.
Veamos el resultado por la consola:
Java Parallel Stream
Como esperábamos hemos tardado 10 segundos en ejecutar el código. ¿Podríamos tardar menos? . En principio si , si dividieramos la tarea en varios Threads . El problema es que no se nos ocurre como dividirla de una forma clara o por lo menos de una forma sencilla. Es aquí donde el manejo de streams es una ventaja. ¿Como podemos realizar la misma operación con Streams?.
package com.arquitecturajava.streams.ejemplo013Paralelos; import java.util.stream.IntStream; public class Principal { public static void main (String[] args) { long numero1=System.currentTimeMillis(); IntStream lista= IntStream.range(1, 10); int total=lista.map(Principal::duplicar).sum(); long numero2=System.currentTimeMillis(); System.out.println(numero2-numero1); System.out.println(total); } public static int duplicar( int numero) { try { Thread.sleep(1000); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } return numero*2; } }
El resultado por la consola es muy similar:
Acabamos de realizar la misma operación utilizando Streams
Java Parallel Stream y sus ventajas
Sin embargo es aquí donde si podemos utilizar de una forma sencilla la programación en paralelo y modificar el número de Threads que se encargan de procesar este Stream.
Para ello nos es suficiente con modificar la siguiente linea y añadir el método parallels para que java lance un conjunto de hilos para realizar la tarea:
int total=lista.parallel().map(Principal::duplicar).sum();
El resultado mejora claramente:
Acabamos de procesar nuestro Stream utilizando varios Threads. Hemos construido nuestro primer ejemplo de Java Parallel Stream.
Otros artículos relacionados:
Buenas, en que casos el uso del parallel() podria dar un nullPointer?
at java.util.stream.ForEachOps$ForEachOp$OfRef.accept(ForEachOps.java:184)
4/1/2021 13:46:03.354 at java.util.ArrayList$ArrayListSpliterator.forEachRemaining(ArrayList.java:1382)
4/1/2021 13:46:03.354 at java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:482)
4/1/2021 13:46:03.354 at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
4/1/2021 13:46:03.354 at java.util.stream.ForEachOps$ForEachTask.compute(ForEachOps.java:291)
4/1/2021 13:46:03.354 at java.util.concurrent.CountedCompleter.exec(CountedCompleter.java:731)
4/1/2021 13:46:03.354 at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92)
4/1/2021 13:46:03.359 at java.util.concurrent.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:157)
4/1/2021 13:46:03.359 at java.util.stream.ForEachOps$ForEachOp$OfRef.accept(ForEachOps.java:184)
No sabria decirte de entrada confirma q la coleccion no llega a nulo
Muchas gracias por este post. Muy bien explicado y muy útil.
gracias 🙂
Hola, gracias por el aporte a la Comunidad.
Me surgen unas dudas. que pasa cuando el procedimiento “DUPLICAR” es complicado, por que en este caso, pusiste a dormir un hilo, pero en el caso de que en verdad uses CPU, como se comporta en tiempos? Cuantos hilos usa? no es lo mismo un I3 que un I9 claramente. En algun momento puede ser peor usar streams paralelos versus seriales?
Perdona el retraso en contestar , se me traspapelo , en principio todo va a depender de la JVM que uno tenga pero en principio lo dividirá entre procesadores
Hola !! Buen articulo, estaria bueno que pudiera hacer un post relacionado al uso de Threads , cuando es recomendable usarlos, cuando no y ese tipo de cuestiones !!
Saludos
Pues cuando tengas mucho volumen de datos
Como odio los Streams ya que son funcionales y poco legibles, pero que bien funcionan!!!.
🙂
gracias por el aporte 🙂
No se ve correctamente el código de “Para ello nos es suficiente con modificar la siguiente linea:”
creo que esta corregido 🙂