web-dev-qa-db-fra.com

Combien de threads sont générés dans parallelStream dans Java 8?

Dans JDK8, combien de threads sont générés lorsque j'utilise parallelStream? Par exemple, dans le code:

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

Si cette liste contient 100 000 éléments, combien de threads seront générés?

En outre, chacun des threads obtient-il le même nombre d'éléments sur lesquels travailler ou est-il attribué de manière aléatoire?

53
SinnerShanky

L'implémentation Oracle [1] du flux parallèle utilise le thread actuel et en plus de cela, si nécessaire, également les threads qui composent le pool de jointure par défaut ForkJoinPool.commonPool(), qui a une taille par défaut égale à un de moins que le nombre de cœurs de votre CPU.

Cette taille par défaut du pool commun peut être modifiée avec cette propriété:

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

Alternativement, vous pouvez utiliser votre propre pool:

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

Concernant l'ordre, les travaux seront exécutés dès qu'un thread sera disponible, sans ordre spécifique.

Comme indiqué correctement par @Holger, il s'agit d'un détail spécifique à l'implémentation (avec juste ne vague référence au bas d'un document), les deux approches fonctionneront sur la JVM d'Oracle mais ne sont certainement pas garanties de fonctionner sur les JVM provenant d'autres fournisseurs, la propriété ne pouvait pas exister dans une implémentation non Oracle et Streams ne pouvait même pas utiliser un ForkJoinPool rendant en interne l'alternative basée sur le comportement de ForkJoinTask.fork complètement inutile ( voir ici pour plus de détails à ce sujet).

56
Umberto Raimondi

Bien que @uraimo soit correct, la réponse dépend exactement de ce que fait "Faire quelque chose". L'API parallel.streams utilise la classe CountedCompleter qui a quelques problèmes intéressants. Étant donné que le framework F/J n'utilise pas d'objet séparé pour contenir les résultats, les longues chaînes peuvent entraîner un OOME. De plus, ces longues chaînes peuvent parfois provoquer un débordement de pile. La réponse à ces problèmes est l'utilisation de la technique paraquentielle comme je l'ai souligné dans cet article.

L'autre problème est la création excessive de threads lors de l'utilisation de forEach parallèle imbriqué.

3
edharned