¿Cuántos subprocesos se generan en paraleloStream en Java 8?


83

En JDK8, ¿cuántos subprocesos se generan cuando estoy usando paralelismo? Por ejemplo, en el código:

list.parallelStream().forEach(/** Do Something */);

Si esta lista tiene 100000 elementos, ¿cuántos hilos se generarán?

Además, ¿cada uno de los subprocesos obtiene la misma cantidad de elementos para trabajar o se asigna al azar?



@assylias Muy buena respuesta.
Umberto Raimondi

Respuestas:


79

La implementación de Oracle [1] de flujo paralelo usa el hilo actual y además de eso, si es necesario, también los hilos que componen el grupo de unión de bifurcación predeterminado ForkJoinPool.commonPool(), que tiene un tamaño predeterminado igual a uno menos que el número de núcleos de su CPU .

Ese tamaño predeterminado de la piscina común se puede cambiar con esta propiedad:

-Djava.util.concurrent.ForkJoinPool.common.parallelism=8

Alternativamente, puede usar su propia piscina:

ForkJoinPool myPool = new ForkJoinPool(8);
myPool.submit(() ->
    list.parallelStream().forEach(/* Do Something */);
).get();

En cuanto al orden, los trabajos se ejecutarán tan pronto como un hilo esté disponible, sin un orden específico.

Como lo señaló correctamente @Holger, este es un detalle específico de implementación (con solo una referencia vaga en la parte inferior de un documento), ambos enfoques funcionarán en la JVM de Oracle, pero definitivamente no se garantiza que funcionen en las JVM de otros proveedores, la propiedad podría no existe en una implementación que no sea de Oracle y Streams ni siquiera podría usar una ForkJoinPoolrepresentación interna de la alternativa basada en el comportamiento de ForkJoinTask.forkcompletamente inútil ( consulte aquí para obtener detalles sobre esto).


5
Quizás valga la pena agregar que si el número de tareas es lo suficientemente pequeño, el flujo paralelo puede ejecutarse en el hilo principal.
assylias

15
Cabe señalar que el Streamuso de API ForkJoinPooles un detalle de implementación. Por lo tanto, ambas soluciones funcionan con la implementación actual de Oracle, pero no se garantiza que funcionen en todas partes.
Holger

4

Si bien @uraimo tiene razón, la respuesta depende exactamente de lo que haga "Hacer algo". La API paralelo.streams usa la clase CountedCompleter que tiene algunos problemas interesantes. Dado que el marco F / J no usa un objeto separado para mantener los resultados, las cadenas largas pueden resultar en un OOME. Además, esas cadenas largas a veces pueden causar un desbordamiento de pila. La respuesta a esos problemas es el uso de la técnica Paraquential como señalé en este artículo.

El otro problema es la creación excesiva de subprocesos cuando se utiliza anidado paralelo forEach.

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.