Bonjour MisterKool,
Oui il me semble qu'il y a quelques erreurs plus ou moins importantes. A ta dispo pour en discuter. Voici ce que j'ai pu relever :
IV-ATu indiques :
Nous insistons sur le terme publique, car avec Java 8, on peut désormais retrouver des méthodes privées dans une interface.
En java 8, les interfaces peuvent avoir des méthodes
public,
static, et
default. Les méthodes privées viennent à partir de java 9.
V-A-2. Méthode submit()Ici il y a une mauvaise utilisation de la méthode
awaitTermination :
1 2 3 4
| counterThreadService.awaitTermination(3, TimeUnit.SECONDS);
if (sommeProduits.isDone()) {
System.out.println("Nombre total de produits dans le magasin : " + sommeProduits.get());
} |
En effet la documentation précise bien :
Blocks until all tasks have completed execution after a shutdown request, or the timeout occur
Or ici aucun shutdown request n'est effectué ! (il est fait après)
La conséquence, c'est qu'il va attendre 3 secondes, même si la tâche se termine bien avant. En fait c'est exactement la même chose que si tu avais mis :
sleep(3000).
Pour ne pas attendre 3 secondes, mais
au maximum 3 secondes (c'est à dire dès que la tâche est terminée si celle ci se termine avant 3 secondes), il faut :
- soit faire un shutdown
avant le
awaitTermination:
- soit remplacer les 4 lignes ci dessus par un simple
sommeProduits.get(3, TimeUnit.SECONDS) : On va bloquer au maximum 3 secondes. Si la tâche se termine avant, on aura le résultat. Si la tâche se termine après, il faut catcher un
TimeoutExceptionV-B-2. Méthode invokeAny()L'exemple et le use case utilisé ici n'est pas du tout adapté à l'utilisation de
invokeAny, ce qui fait que le résultat produit pourra être faux.
Tu utilises
invokeAny pour rechercher en parallèle une valeur dans deux ensembles. Tu supposes alors que le premier qui a trouvé la valeur, retournera son résultat.
Or ce n'est pas le premier qui trouve la valeur qui retourne, mais le premier qui finit sa recherche !! Et ça change tout. Si dans l'ensemble 1 / thread 1, tu as la valeur 1500 recherchée. Et dans l'ensemble 2 / thread 2 tu n'as pas cette valeur. Et que thread 2 termine sa recherche avant thread 1, tu auras alors le message
"Aucun thread n a trouvé le CA 1500 recherché". Alors que cette valeur existe dans l'ensemble 1 !
Le cas est très facile à reproduire. Tu crées une liste de 500 valeurs non pas random, mais fixes, un ensemble contenant la valeur recherchée et l'autre non. Tu lances plusieurs fois ton programme, et tu verras que le résultat diffère alors que la liste est fixe, et donc que le résultat devrait être toujours le même.
Pour corriger, il suffit pour les thread ne trouvant pas la valeur, de lancer une exception, et non de renvoyer le message
"Aucun thread n a trouvé le CA 1500 recherché". La documentation précisant :
Executes the given tasks, returning the result of one that has completed successfully (i.e., without throwing an exception)
- Si une tâche se termine sans erreurs, c'est qu'elle a trouvé la valeur
- Si aucune tâche ne trouve la valeur, invokeAny lancera une
ExecutionExceptionV-D-2. Méthode scheduleWithFixedDelay()Même remarque pour le
awaitTermination qui ne sert pas à grand chose si
shutdown n'a pas été appelé. Un simple
sleep permet d'attendre le temps voulu.
V-D-3. Méthode scheduleAtFixedRate()Tu indiques :
que si l'on defini une période de trois minutes par exemple, que la durée d'exécution d'une tâche dure quatre minutes, alors toutes les 3 minutes un nouveau thread sera créé, quitte à avoir plusieurs threads en exécution parallèlesC'est incorrect, aucune thread n'est crée pour compenser une tâche qui serait plus longue que le rate indiqué. Si le cas arrive, la tâche suivante se lance dès que la tâche précédente est terminée.
Tu peux le lire dans la documentation de
scheduleAtFixedRate :
If any execution of this task takes longer than its period, then subsequent executions may start late, but
will not concurrently execute
Et de manière générale (c'est un détail !), pour faire des opérations sur les streams contenant des types primitifs (int et long), tu utilises reduce pour faire des opérations simples comme min et sum, alors qu'il est plus efficace (normalement moins d'autoboxing) et plus lisible d'utiliser les méthodes sum() et min() sur les streams primitifs IntStream et LongStream, obtenu par les méthodes mapToInt et mapToLong sur les stream<Integer> et stream<Long>.
En espérant avoir pu aider
Cordialement
1 |
0 |