web-dev-qa-db-fra.com

Différence détaillée entre Java8 ForkJoinPool et Executors.newWorkStealingPool?

Quelle est la différence de bas niveau entre l'utilisation:

ForkJoinPool = new ForkJoinPool(X);

et

ExecutorService ex = Executors.neWorkStealingPool(X);

Xest le niveau de parallélisme souhaité, c'est-à-dire que les threads sont en cours d'exécution.

Selon les docs, je les ai trouvés similaires. Dites-moi également lequel est le plus approprié et le plus sûr pour toute utilisation normale. J'ai 130 million d'entrées à écrire dans un BufferedWriter et à les trier à l'aide du tri Unix par 1ère colonne.

Dites-moi aussi combien de fils à garder si possible.

Remarque: Mon système dispose de 8 processeurs principaux et 32 Go de RAM.

11
bit_cracker007

Le vol de travail est une technique utilisée par les pools de threads modernes afin de réduire les conflits sur la file d'attente de travail.

Un pool de threads classique a une file d'attente et chaque thread-pool-thread verrouille la file d'attente, libère une tâche, puis la déverrouille. si les tâches sont courtes et qu’elles sont nombreuses, la file d’attente est très controversée. L'utilisation d'une file d'attente sans verrouillage est vraiment utile, mais ne résout pas le problème complètement.

Les pools de threads modernes utilisent le vol de travail - chaque thread a sa propre file d'attente. lorsqu'un thread threadpool produit une tâche, il la met en file d'attente dans sa propre file d'attente. lorsqu'un thread de pool de threads veut retirer une tâche d'une tâche - il essaie d'abord de retirer une tâche de sa propre file d'attente et s'il n'en a pas - il "vole" le travail des autres files d'attente de threads. cela diminue vraiment la contention du theradpool et améliore les performances.

newWorkStealingPool crée un pool de threads utilisant le workstealing avec le nombre de threads correspondant au nombre de processeurs.

newWorkStealingPool présente un nouveau problème. Si j'ai quatre cœurs logiques, le pool aura au total quatre threads. si mes tâches se bloquent - par exemple sur IO synchrone -, je n'utilise pas assez mes processeurs. ce que je veux, ce sont quatre actifs threads à à tout moment , par exemple - quatre threads qui chiffrent AES et 140 autres threads qui attendent la fin du IO.

c'est ce que ForkJoinPool fournit - si votre tâche génère de nouvelles tâches et que cette tâche les attend pour se terminer - le pool injectera de nouveaux threads actifs afin de saturer le processeur. Il est à noter que ForkJoinPool utilise aussi le vol de travail.

lequel utiliser? si vous travaillez avec le modèle de jointure à la fourche ou si vous connaissez le blocage indéfini de vos tâches, utilisez la variable ForkJoinPool. Si vos tâches sont courtes et liées principalement au processeur, utilisez newWorkStealingPool.

et après tout, les applications modernes ont tendance à utiliser un pool de threads avec le nombre de processeurs disponibles et à utiliser asynchrone IO et lock-free-containers afin d'éviter le blocage. cela (généralement) donne les meilleures performances.

15
David Haim

newWorkStealingPool est un niveau d'abstraction supérieur pour ForkJoinPool.

Si vous regardez l'implémentation Oracle jvm, il s'agit simplement d'une ForkJoinPool: public static ExecutorService newWorkStealingPool() { return new ForkJoinPool (Runtime.getRuntime().availableProcessors(), ForkJoinPool.defaultForkJoinWorkerThreadFactory, null, true); } préconfigurée. Malheureusement, examiner l'implémentation n'est pas un moyen approprié de comprendre le but d'une classe. Crédit également à: https://dzone.com/articles/diving-into-Java-8s-newworkstealingpools

1
Yamcha

Ce n'est qu'une abstraction pour Fork/Join Framework ...

/**
* Creates a work-stealing thread pool using all
* {@link Runtime#availableProcessors available processors}
* as its target parallelism level.
* @return the newly created thread pool
* @see #newWorkStealingPool(int)
* @since 1.8
*/
public static ExecutorService newWorkStealingPool() {
    return new ForkJoinPool(Runtime.getRuntime().availableProcessors(),
                            ForkJoinPool.defaultForkJoinWorkerThreadFactory,
                            null, true);
}
0
Rafael Bernabeu