J'essaie de traiter le code ci-dessous en utilisant le multithreading au niveau de la commande.
List<String> orders = Arrays.asList("order1", "order2",
"order3", "order4", "order1");
Exécution séquentielle actuelle:
orders.stream().forEach(order -> {
rules.forEach(rule -> {
finalList.add(beanMapper.getBean(rule)
.applyRule(createTemplate.apply(getMetaData.apply(rule), command),
order));
});
});
J'ai essayé d'utiliser:
orders.parallelStream().forEach(order -> {}} // code snippet.
Mais cela modifie l'ordre rules.forEach (rule -> {}} .
Par exemple:
Entrée:
List<String> orders = Arrays.asList("order1", "order2",
"order3", "order4", "order1");
List<String> rules = Arrays.asList("rule1", "rule2", "rule3");
Production attendue:
order1 with rule1, rule2, rule3
order2 with rule1, rule2, rule3
Sortie réelle avec parallelStream()
:
order1 with rule3, rule1, rule2
order1 with rule2, rule1, rule3
Je ne m'inquiète pas de l'ordre des commandes , mais je m'inquiète de l'ordre des règles . Les commandes peuvent être traitées dans n'importe quel ordre, mais les règles doivent s'exécuter dans le même ordre pour chaque ordre.
Veuillez aider.
la source
Vous ajoutez des éléments aux
finalList
différents threads en même temps. Cela provoque un mélange des résultats de l'application des règles à différents ordres (les règles ne sont pas regroupées par leurs ordres).Vous pouvez le corriger en créant une liste temporaire pour chacun
order
, puis en fusionnant de manière synchrone toutes les listes temporaires dans un fichierfinalList
.Voici comment vous pouvez le faire en utilisant Stream-API (Java 9+):
Remarque:
Collectors.flatMapping()
est utilisé ici au lieu de simpleflatMap
pour exécuter un mappage plat de manière synchrone pendant la collecte de flux.Analogue Java 8:
la source
beanMapper.getBean(rule) .applyRule(createTemplate.apply(getMetaData.apply(rule), command), order)
n'est pas une fonction pure, donc elle ne peut pas être utilisée en parallèle. Essayez d'en supprimer tous les effets secondaires;ConcurrentModificationException
la trace de la pile peut aider à les localiser.Est-ce que ça va marcher?
Production
la source
Si tel est le cas, il n'y a pas de place pour un parallélisme réel.
Quand
et
sont les seules séries valides pour 2 commandes et 2 règles,
et
est considéré comme invalide, ce n'est pas du parallélisme, juste une randomisation de
order
s, sans doute sans gain. Si vous "vous ennuyez" enorder1
venant tout le temps en premier, vous pouvez mélanger la liste, mais c'est tout:Même le streaming n'est pas nécessaire, juste deux boucles imbriquées. Test: https://ideone.com/qI3dqd
Réponse originale
Non. Les
order
s peuvent se chevaucher, mais l'ordre desrule
s pour chaque commande est conservé. Pourquoi un non-parallèleforEach
ferait-il autre chose?Exemple de code:
Test: https://ideone.com/95Cybg
Exemple de sortie:
L'ordre des
order
s est mixte, mais lesrule
s sont toujours 1-2-3. Je pense que votre sortie a simplement caché les appariements (en fait, vous n'avez pas montré comment elle a été générée).Bien sûr, il peut être étendu avec quelques retards, donc le traitement des
order
s se chevauchera en fait:Test: https://ideone.com/cSFaqS
Exemple de sortie:
Cela peut être quelque chose que vous avez vu, juste sans la
orderx
partie. Avec leorder
s visible, il peut être suivi querule
s continue à venir comme 1-2-3, parorder
. De plus, votre liste d'exemples contenaitorder1
deux fois, ce qui n'a certainement pas aidé à voir ce qui se passait.la source
order
s ne peuvent pas se chevaucher (ceux-ci sont-ilsrule
peut-être avec état et existent-ils en un nombre limité d'exemplaires, peut-être un seul?). Mais généralement, il n'y a pas de parallélisme sans que les choses tournent en parallèle, c'est tout l'intérêt du parallélisme après tout.Si cela ne vous dérange pas d'essayer une bibliothèque tierce. Voici un exemple avec ma bibliothèque: abacus-util
Et vous pouvez même spécifier le numéro de fil:
L'ordre de
rule
sera conservé.Soit dit en passant, puisqu'il est en flux parallèle, le morceau de code
...finalList.add(...
ne fonctionnera probablement pas. Je pense qu'il vaut mieux collecter le résultat pour lister:il est également possible même si vous souhaitez conserver l'ordre de
order
pour une raison ultérieure:la source