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?
java
multithreading
java-8
java.util.concurrent
shashankg77
fuente
fuente
Respuestas:
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
ForkJoinPool
representación interna de la alternativa basada en el comportamiento deForkJoinTask.fork
completamente inútil ( consulte aquí para obtener detalles sobre esto).fuente
Stream
uso de APIForkJoinPool
es 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.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.
fuente