Ich versuche, den folgenden Code mithilfe von Multithreading auf Auftragsebene zu verarbeiten.
List<String> orders = Arrays.asList("order1", "order2",
"order3", "order4", "order1");
Aktuelle sequentielle Ausführung:
orders.stream().forEach(order -> {
rules.forEach(rule -> {
finalList.add(beanMapper.getBean(rule)
.applyRule(createTemplate.apply(getMetaData.apply(rule), command),
order));
});
});
Ich habe versucht mit:
orders.parallelStream().forEach(order -> {}} // code snippet.
Aber es ändert die Regeln für jede (Regel -> {}} Reihenfolge.
Zum Beispiel:
Eingabe:
List<String> orders = Arrays.asList("order1", "order2",
"order3", "order4", "order1");
List<String> rules = Arrays.asList("rule1", "rule2", "rule3");
Erwartete Ausgabe:
order1 with rule1, rule2, rule3
order2 with rule1, rule2, rule3
Tatsächliche Ausgabe mit parallelStream()
:
order1 with rule3, rule1, rule2
order1 with rule2, rule1, rule3
Die Reihenfolge der Bestellungen stört mich nicht , aber die Reihenfolge der Regeln stört mich . Bestellungen können in beliebiger Reihenfolge verarbeitet werden, Regeln sollten jedoch für jede Bestellung in derselben Reihenfolge ausgeführt werden.
Bitte helfen Sie.
quelle
Sie fügen gleichzeitig Elemente
finalList
aus verschiedenen Threads hinzu. Dies führt zu Mischergebnissen beim Anwenden von Regeln auf verschiedene Aufträge (Regeln werden nicht nach ihren Aufträgen gruppiert).Sie können das Problem beheben, indem Sie für jede Liste eine temporäre Liste erstellen
order
und dann alle temporären Listen in a synchron zusammenführenfinalList
.So können Sie es mit der Stream-API (Java 9+) machen:
Hinweis:
Collectors.flatMapping()
Wird hier verwendet, anstattflatMap
das Flat Mapping während der Stream-Erfassung einfach synchron auszuführen.Java 8 analog:
quelle
beanMapper.getBean(rule) .applyRule(createTemplate.apply(getMetaData.apply(rule), command), order)
keine reine Funktion ist und daher nicht parallel verwendet werden kann. Versuchen Sie, alle Nebenwirkungen zu entfernen.ConcurrentModificationException
Stack-Trace kann helfen, sie zu finden.Ob das funktioniert?
Ausgabe
quelle
Wenn dies der Fall ist, gibt es keinen Raum für tatsächliche Parallelität.
Wann
und
sind die einzigen gültigen Läufe für 2 Bestellungen und 2 Regeln,
und
wird als ungültig angesehen, das heißt nicht Parallelität, sondern Randomisierung von
order
s, vermutlich ohne Gewinn. Wenn Sie sich "langweilen"order1
, immer an erster Stelle zu stehen, können Sie die Liste mischen, aber das ist alles:Es ist nicht einmal Streaming erforderlich, nur zwei verschachtelte Schleifen. Test: https://ideone.com/qI3dqd
Ursprüngliche Antwort
Nein, tut es nicht. Das
order
s kann sich überlappen, aber die Reihenfolge vonrule
s für jede Reihenfolge wird beibehalten. Warum sollte ein Nicht-ParallelerforEach
etwas anderes tun?Beispielcode:
Test: https://ideone.com/95Cybg
Beispielausgabe:
Die Reihenfolge von
order
s ist gemischt, aber dierule
s sind immer 1-2-3. Ich denke, Ihre Ausgabe hat die Paarungen einfach versteckt (tatsächlich haben Sie nicht gezeigt, wie sie generiert wurden).Natürlich kann es mit einigen Verzögerungen verlängert werden, also Verarbeitung von
order
s tatsächlich überschneidet:Test: https://ideone.com/cSFaqS
Beispielausgabe:
Dies kann etwas sein, was Sie gesehen haben, nur ohne das
orderx
Teil. Mit demorder
sichtbaren s kann verfolgt werden, dassrule
s immer wieder als 1-2-3 pro kommtorder
. Außerdem enthielt Ihre Beispiellisteorder1
zweimal, was sicherlich nicht dazu beitrug, zu sehen, was geschah.quelle
order
s sich nicht überlappen können (sind dieserule
s möglicherweise zustandsbehaftet und existieren in einer begrenzten Anzahl von Kopien, vielleicht nur einer einzigen?). Aber im Allgemeinen gibt es keine Parallelität ohne parallele Dinge, das ist schließlich der springende Punkt der Parallelität.Wenn es Ihnen nichts ausmacht, die Bibliothek eines Drittanbieters auszuprobieren. Hier ist ein Beispiel mit meiner Bibliothek: abacus-util
Und Sie können sogar die Thread-Nummer angeben:
Die Reihenfolge von
rule
wird eingehalten.Übrigens, da es sich um einen parallelen Stream handelt, wird der Code
...finalList.add(...
höchstwahrscheinlich nicht funktionieren. Ich denke, es ist besser, das Ergebnis zu sammeln, um es aufzulisten:Dies ist auch dann möglich, wenn Sie die Reihenfolge
order
später aus irgendeinem Grund beibehalten möchten :quelle