Wie viele Threads werden in JDK8 erzeugt, wenn ich parallelStream verwende? Zum Beispiel im Code:
list.parallelStream().forEach(/** Do Something */);
Wenn diese Liste 100000 Elemente enthält, wie viele Threads werden erzeugt?
Bekommt jeder der Threads die gleiche Anzahl von Elementen, an denen gearbeitet werden soll, oder wird er zufällig zugewiesen?
java
multithreading
java-8
java.util.concurrent
shashankg77
quelle
quelle
Antworten:
Die Oracle-Implementierung [1] von Parallel Stream verwendet den aktuellen Thread und bei Bedarf zusätzlich auch die Threads, aus denen der Standard-Fork-Join-Pool besteht
ForkJoinPool.commonPool()
, dessen Standardgröße eins weniger als die Anzahl der Kerne Ihrer CPU beträgt .Diese Standardgröße des gemeinsamen Pools kann mit dieser Eigenschaft geändert werden:
-Djava.util.concurrent.ForkJoinPool.common.parallelism=8
Alternativ können Sie Ihren eigenen Pool verwenden:
ForkJoinPool myPool = new ForkJoinPool(8); myPool.submit(() -> list.parallelStream().forEach(/* Do Something */); ).get();
In Bezug auf die Reihenfolge werden Jobs ausgeführt, sobald ein Thread verfügbar ist, und zwar in keiner bestimmten Reihenfolge.
Wie von @Holger richtig hervorgehoben, handelt es sich um ein implementierungsspezifisches Detail (mit nur einem vagen Verweis am Ende eines Dokuments). Beide Ansätze funktionieren mit der JVM von Oracle, es ist jedoch definitiv nicht garantiert, dass sie mit JVMs anderer Anbieter funktionieren in einer Nicht-Oracle-Implementierung nicht vorhanden und Streams konnten nicht einmal ein
ForkJoinPool
internes Rendern der Alternative verwenden, basierend auf dem Verhalten vonForkJoinTask.fork
völlig nutzlos ( siehe hier für Details dazu).quelle
Stream
Verwendung von APIsForkJoinPool
ein Implementierungsdetail ist. Daher funktionieren beide Lösungen mit der aktuellen Implementierung von Oracle, es ist jedoch nicht garantiert, dass sie überall funktionieren.Während @uraimo korrekt ist, hängt die Antwort genau davon ab, was "Do Something" tut. Die parallel.streams-API verwendet die CountedCompleter-Klasse, die einige interessante Probleme aufweist. Da das F / J-Framework kein separates Objekt zum Speichern von Ergebnissen verwendet, können lange Ketten zu einem OOME führen. Auch diese langen Ketten können manchmal einen Stapelüberlauf verursachen. Die Antwort auf diese Probleme ist die Verwendung der Paraquential-Technik, wie ich in diesem Artikel ausgeführt habe.
Das andere Problem ist die übermäßige Thread-Erstellung, wenn verschachtelte parallele forEach verwendet werden.
quelle