© Excellent backgrounds/Shutterstock.com
Java Magazin
Effective Java - Teil 12

Java 8: Parallele Streams

Die grundlegende Funktionalität von Java 8 Streams haben wir ja bereits in den Folgen unter [1] bis [4] erläutert - im vorliegenden und den folgenden Beiträgen wollen wir noch einmal zu den Streams zurückkehren und uns die fortgeschritteneren Themen ansehen. Beginnen wollen wir mit den parallelen Streams.

Angelika Langer, Klaus Kreft


Video: Programmiertechniken mit Lambda-Ausdrücken und Interface-Methoden

Fangen wir damit an, zu betrachten, wie sich sequenzielle und parallele Streams unterscheiden und welche Gemeinsamkeiten sie haben. Die grundsätzliche Idee besteht darin, dass sequenzielle Streams ihre Funktionalität sequenziell in einem einzigen Thread ausführen, während parallele Streams dies parallel mit mehreren Threads machen. Schauen wir uns dazu ein Beispiel an: Nehmen wir an, ints ist ein großes int-Array, in dem wir das größte Element suchen wollen. Mit einem sequenziellen Stream geht dies so:

int max = Arrays.stream(ints).reduce(Integer.MIN_VALUE, Math::max);

Mit einem parallelen Stream hingegen so:

int max = Arrays.stream(ints).parallel().reduce(Integer.MIN_VALUE, Math::max);

Beim sequenziellen Stream sucht ein einziger Thread das größte Element, beim parallelen Stream sind es (im Default-Fall auf einer Multi-Core-Plattform) so viele Threads, wie es CPU-Cores auf der unterliegenden Plattform gibt. Weitere Details zur parallelen Verarbeitung sehen wir weiter unten an. Die grundsätzliche Erwartung ist, dass durch die Nutzung mehrerer parallel arbeitender Threads der parallele Stream mit seiner Arbeit schneller fertig wird als der sequenzielle und damit die Performance unseres Java-Programms verbessert wird.

Aus JDK-Benutzersicht ist die Nutzung paralleler Streams ziemlich einfach. Im Fall von Arrays (unser Beispiel oben) wird der zusätzliche Aufruf der Streammethode parallel() benötigt. Bei Collections ruft man bei der Streamerzeugung auf dem Collection-Objekt statt stream() die Methode parallelStream() auf [2]. Das heißt, mit einem sequenziellen Stream suchen wir das größte Element in einer intList (vom Typ List) so:

int max = intList.stream().reduce(Integer.MIN_VALUE, Math::max);

Mit einem parallelen Stream so:

int max = intList.parallelStream().reduce(Integer.MIN_VALUE, Math::max);

Sonst ändert sich für den JDK-Benutzer im Wesentlichen nichts. In beiden Fällen ist der statische Streamtyp, auf dem man dann die weitere Streamfunktionalität aufruft, der gleiche, nämlich java.util.Stream (und in dem Beispiel mit dem int-Array weiter oben: java.util.IntStream). Das heißt, es gibt keine unterschiedlichen Typen für sequenzielle und parallele Funktionalität. Es gibt nur einen Streamtyp, der beide Möglichkeiten anbietet. Dies zeigt sich bei den Anforderungen an Parameter von Streamoperationen bzw. bei den Zusicherungen an Ergebnisse von Streamoperationen, die in der Javadoc von ja...

Java Magazin
Effective Java - Teil 12

Java 8: Parallele Streams

Die grundlegende Funktionalität von Java 8 Streams haben wir ja bereits in den Folgen unter [1] bis [4] erläutert - im vorliegenden und den folgenden Beiträgen wollen wir noch einmal zu den Streams zurückkehren und uns die fortgeschritteneren Themen ansehen. Beginnen wollen wir mit den parallelen Streams.

Angelika Langer, Klaus Kreft


Video: Programmiertechniken mit Lambda-Ausdrücken und Interface-Methoden

Fangen wir damit an, zu betrachten, wie sich sequenzielle und parallele Streams unterscheiden und welche Gemeinsamkeiten sie haben. Die grundsätzliche Idee besteht darin, dass sequenzielle Streams ihre Funktionalität sequenziell in einem einzigen Thread ausführen, während parallele Streams dies parallel mit mehreren Threads machen. Schauen wir uns dazu ein Beispiel an: Nehmen wir an, ints ist ein großes int-Array, in dem wir das größte Element suchen wollen. Mit einem sequenziellen Stream geht dies so:

int max = Arrays.stream(ints).reduce(Integer.MIN_VALUE, Math::max);

Mit einem parallelen Stream hingegen so:

int max = Arrays.stream(ints).parallel().reduce(Integer.MIN_VALUE, Math::max);

Beim sequenziellen Stream sucht ein einziger Thread das größte Element, beim parallelen Stream sind es (im Default-Fall auf einer Multi-Core-Plattform) so viele Threads, wie es CPU-Cores auf der unterliegenden Plattform gibt. Weitere Details zur parallelen Verarbeitung sehen wir weiter unten an. Die grundsätzliche Erwartung ist, dass durch die Nutzung mehrerer parallel arbeitender Threads der parallele Stream mit seiner Arbeit schneller fertig wird als der sequenzielle und damit die Performance unseres Java-Programms verbessert wird.

Aus JDK-Benutzersicht ist die Nutzung paralleler Streams ziemlich einfach. Im Fall von Arrays (unser Beispiel oben) wird der zusätzliche Aufruf der Streammethode parallel() benötigt. Bei Collections ruft man bei der Streamerzeugung auf dem Collection-Objekt statt stream() die Methode parallelStream() auf [2]. Das heißt, mit einem sequenziellen Stream suchen wir das größte Element in einer intList (vom Typ List) so:

int max = intList.stream().reduce(Integer.MIN_VALUE, Math::max);

Mit einem parallelen Stream so:

int max = intList.parallelStream().reduce(Integer.MIN_VALUE, Math::max);

Sonst ändert sich für den JDK-Benutzer im Wesentlichen nichts. In beiden Fällen ist der statische Streamtyp, auf dem man dann die weitere Streamfunktionalität aufruft, der gleiche, nämlich java.util.Stream (und in dem Beispiel mit dem int-Array weiter oben: java.util.IntStream). Das heißt, es gibt keine unterschiedlichen Typen für sequenzielle und parallele Funktionalität. Es gibt nur einen Streamtyp, der beide Möglichkeiten anbietet. Dies zeigt sich bei den Anforderungen an Parameter von Streamoperationen bzw. bei den Zusicherungen an Ergebnisse von Streamoperationen, die in der Javadoc von ja...

Neugierig geworden?


    
Loading...

Angebote für Teams

Für Firmen haben wir individuelle Teamlizenzen. Wir erstellen Ihnen gerne ein passendes Angebot.

Das Library-Modell:
IP-Zugang

Das Company-Modell:
Domain-Zugang