1

Bonjour je pensais avec CompletableFuture et la valeur par défaut ForkJoinPool je pourrais optimiser l'exécution de la tâche plus d'un classique ExecutorService mais je manque quelque choseutilisation CompletableFuture sur ForkJoinpool et éviter thread en attente

Avec ce code l'exécution prend 1 seconde, je 3 threads de travail:

for (int i = 0; i < 3; i++) { 
    final int counter = i; 
    listTasks.add(CompletableFuture.supplyAsync(() -> { 
     Thread.sleep(1000); 
     System.out.println("Looking up " + counter + " on thread " + Thread.currentThread().getName()); 
     return null; 
    })); 
} 

OK, semble normal.

Mais avec ce code, il faut 3 secondes:

for (int i = 0; i < 9; i++) { 
    final int counter = i; 
    listTasks.add(CompletableFuture.supplyAsync(() -> { 
     Thread.sleep(1000); 
     System.out.println("Looking up " + counter + " on thread " + Thread.currentThread().getName()); 
     return null; 
    })); 
} 

Je pensais que le fil du sommeil serait utilisé pour lancer d'autres tâches en attente, il devrait aussi prend 1 seconde. J'ai lu par exemple que l'état de thread IO WAINTING signifierait que le thread peut être réutilisé pour une autre tâche. Puis-je tester ce comportement avec Thread.sleep()? Ma méthode de test est-elle incorrecte ou ai-je mal compris quelque chose?

+0

Combien de processeurs avez-vous sur votre ordinateur? –

+0

Salut, 2 réels, mais j'ai mis cela pour forcer 3 travailleurs et éviter le thread de fonte: 'System.setProperty (" java.util.concurrent.ForkJoinPool.common.parallelism "," 3 ");' – bodtx

Répondre

1

Un thread dormant ne peut pas être utilisé pour faire le travail d'un autre thread (en particulier, un thread ne peut pas dormir pour un autre thread). C'est seulement le CPU qui peut passer au second thread quand le premier se met en veille.

Lorsque vous attribuez une tâche à CompletableFuture.supplyAsync(), l'instance par défaut, ForkJoinPool, comporte autant de threads que votre ordinateur est équipé de processeurs. Vous définissez manuellement trois threads alloués à votre ForkJoinPool par défaut, de sorte que vos neuf tâches sont réparties équitablement entre eux: chaque thread exécute trois tâches de manière consécutive. Donc, vous avez trois secondes comme résultat.

+0

Ok, merci pour le sommeil mais si je fais IO comme l'écriture de fichier ou l'appel de service web au lieu de Thread.sleep, aurai-je le même résultat ou est-ce que le thread Waiting sera réutilisé pour lancer une autre requête IO/Web? – bodtx

+0

Si votre thread est gelé pendant une seconde pour faire quelques E/S, vous aurez absolument le même effet. –

+0

Dans votre cas, vous avez trois threads et ils sélectionnent les tâches disponibles dans la file d'attente partagée. Vous mettez neuf tâches dans cette file d'attente. Chaque thread prend une tâche, l'exécute complètement (dort une seconde) et ensuite seulement prend une autre tâche. Mais le processeur en même temps (pendant que vos threads dorment) a une chance de passer à un autre thread (y compris les threads d'un autre processus) et de faire un travail utile. –

1

Faisons le calcul. Si vous avez 9 tâches et que chaque tâche dort pendant 1 seconde et que vous avez 2 processeurs, vous ne pouvez exécuter que 2 sessions de 1 seconde à la fois. Exécutez ceci avec 9 tâches et vous obtenez au moins 3 secondes écoulées ou tout au plus 4 secondes écoulées. Ce n'est pas la même chose que les E/S non bloquantes car ce thread Runnable est lié à la CPU et n'abandonnera pas le CPU jusqu'à la fin (malgré le temps de veille). Si vous regardez des choses comme le pool de threads IO de RxJava, il crée un thread par tâche qui est acceptable pour les tâches IO (mais pas pour les tâches liées au CPU).

+0

Convenir avec les maths, sauf s'il y avait un changement de contexte possible. Mais comme vous le dites et comme RxJava semble le faire avec IO Thread Pool, un thread ne peut pas changer de contexte même s'il est bloqué dans IO. ok [this] (http://stackoverflow.com/a/28402906/1077548) explique comment cela fonctionne avec servlet, en effet il n'y a pas de changement de contexte magique, seulement ThreadPool pour les threads bloqués – bodtx