web-dev-qa-db-fra.com

Pourquoi le flux parallèle n'utilise-t-il pas tous les threads de ForkJoinPool?

Je sais donc que si vous utilisez le parallelStream sans ForkJoinPool personnalisé, il utilisera le ForkJoinPool par défaut qui, par défaut, a un thread de moins car vous avez des processeurs.

Donc, comme indiqué ici (et aussi dans l'autre réponse de cette question) afin d'avoir plus de parallélisme, vous devez:

soumettez l'exécution du flux parallèle à votre propre ForkJoinPool: yourFJP.submit (() -> stream.parallel (). forEach (doSomething));

Alors j'ai fait ça:

import Java.util.Set;
import Java.util.concurrent.ExecutionException;
import Java.util.concurrent.ForkJoinPool;
import Java.util.stream.IntStream;
import com.google.common.collect.Sets;

public class Main {

    public static void main(String[] args) throws InterruptedException, ExecutionException {

        ForkJoinPool forkJoinPool = new ForkJoinPool(1000);

        IntStream stream = IntStream.range(0, 999999);

        final Set<String> thNames = Collections.synchronizedSet(new HashSet<String>());

        forkJoinPool.submit(() -> {
            stream.parallel().forEach(n -> {

                System.out.println("Processing n: " + n);
                try {
                    Thread.sleep(500);
                    thNames.add(Thread.currentThread().getName());
                    System.out.println("Size: " + thNames.size() + " activeCount: " + forkJoinPool.getActiveThreadCount());
                } catch (Exception e) {
                    throw new RuntimeException(e);
                }
            });
        }).get();
    }
}

J'ai créé un ensemble de noms de threads afin de voir combien de threads sont créés, et j'ai également enregistré le nombre de threads actifs que possède le pool et les deux nombres n'augmentent pas plus de 16, ce qui signifie que le parallélisme ici est ne pas avoir plus de 16 ans (pourquoi même 16 ans). Si je n'utilise pas le forkJoinPool, j'obtiens 4 comme parallélisme, ce qui dépend du nombre de processeurs que j'ai.

Pourquoi me donne-t-il 16 et non 1000?

14
Pablo Matias Gomez

Mise à jour

À l'origine, cette réponse était une explication élaborée affirmant que le ForkJoinPool applique une contre-pression et n'atteint même pas le niveau de parallélisme prescrit, car il y a toujours des travailleurs inactifs disponibles pour traiter le flux.

C'est incorrect.

La réponse réelle est fournie dans la question d'origine à laquelle cela a été marqué comme doublon - l'utilisation d'un ForkJoinPool personnalisé pour le traitement de flux n'est pas officiellement prise en charge, et lors de l'utilisation de forEach, le parallélisme de pool par défaut est utilisé pour déterminer le comportement du séparateur de flux.

Voici un exemple de la façon dont lorsque les tâches sont soumises manuellement à un ForkJoinPool personnalisé, le nombre de threads actifs du pool atteint facilement son niveau de parallélisme:

for (int i = 0; i < 1_000_000; ++i) {
   forkJoinPool.submit(() -> {
      try {
         Thread.sleep(1);
         thNames.add(Thread.currentThread().getName());
         System.out.println("Size: " + thNames.size() + " activeCount: " + forkJoinPool.getActiveThreadCount() + " parallelism: " + forkJoinPool.getParallelism());
      } catch (Exception e) {
         throw new RuntimeException(e);
      }
   });
}

Merci à Stuart Marks pour l'avoir signalé et à Sotirios Delimanolis pour avoir soutenu que ma réponse originale était fausse :)

11
Dimitar Dimitrov