Wie viele Threads werden in parallelStream in Java 8 erzeugt?


79

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?



@assylias Wirklich gute Antwort.
Umberto Raimondi

Antworten:


77

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 ForkJoinPoolinternes Rendern der Alternative verwenden, basierend auf dem Verhalten von ForkJoinTask.forkvöllig nutzlos ( siehe hier für Details dazu).


5
Vielleicht lohnt es sich hinzuzufügen, dass der parallele Stream tatsächlich im Hauptthread ausgeführt wird, wenn die Anzahl der Aufgaben klein genug ist.
Assylias

15
Es ist zu beachten, dass die StreamVerwendung von APIs ForkJoinPoolein Implementierungsdetail ist. Daher funktionieren beide Lösungen mit der aktuellen Implementierung von Oracle, es ist jedoch nicht garantiert, dass sie überall funktionieren.
Holger

4

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.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.