© Excellent backgrounds/Shutterstock.com
Java Magazin
Streams und blockierende Funktionalität

Einmal um den Block

Diesmal wollen wir uns genauer ansehen, wie parallele Streams mit blockierender Funktionalität umgehen und welche Möglichkeiten man als Stream-Nutzer hat, sie dabei zu beeinflussen.

Angelika Langer, Klaus Kreft


In der Softwarearchitektur gibt es das grundsätzliche Prinzip, den Durchsatz bei blockierender Funktionalität durch die Verwendung von mehreren parallelen Threads zu erhöhen. Typische Beispiele für blockierende Funktionalität sind synchrone Netzwerk-I/O über HTTP oder synchrone Datenbankzugriffe über JDBC. Verwendet man mehrere Threads, um diese blockierende Funktionalität parallel auszuführen, so lässt sich im Allgemeinen der Durchsatz steigern. Um solche Lösungen mit mehreren parallelen Threads zu implementieren, ist einiges an Design- und Implementierungsaufwand erforderlich. Außerdem braucht man im Bereich von Multi-Thread Programming ausreichendes Know-how, z. B. zum Umgang mit Threadpools oder zur Ergebnissynchronisation.

Jetzt, da parallele Streams ein Teil der JDKs sind, gibt es die Hoffnung, dass sich solche Lösungen deutlich einfacher implementieren lassen: Man übergibt einfach die blockierende Funktionalität in einem Lambda-Ausdruck an eine geeignete Stream-Operation eines parallelen Streams. Leider sind parallele Streams dafür nicht uneingeschränkt geeignet. Wo die Probleme einer solchen Lösung sind und welche zusätzlichen Möglichkeiten man als Stream-Nutzer hat, diese Probleme zu umgehen oder zu minimieren, wollen wir uns im vorliegenden Artikel im Detail ansehen.

Blockierende Funktionalität: ein Beispiel

Schauen wir uns zuerst ein konkretes Beispiel für blockierende Funktionalität an. Wir wollen uns mithilfe eines HTTP-Requests Informationen, Symbol, Aktienkurs, sowie Veränderung des Kurses zu dem Tickersymbol eines börsennotierten Unternehmens holen (Listing 1).

Listing 1public static String getStockInfo(String s) { try { URL yahoofinance = new URL("http://finance.yahoo.com/d/quotes.csv?s="+ s +"&f=sl1c");  URLConnection yc = yahoofinance.openConnection();  try (BufferedReader in = new BufferedReader(new InputStreamReader(yc.getInputStream()))) {  String result = in.readLine(); return result; } } catch (Exception e) { return null; }}

Diese blockierende Funktionalität übergeben wir in einem Lambda-Ausdruck an die map()-Operation eines Streams. Das heißt, in der map()-Operation wird das Tickersymbol (String) auf einen Ergebnis-String abgebildet, der Symbol, Aktienkurs sowie Veränderung des Kurses enthält. Die gesamte Stream-Verarbeitung ist in Listing 2 zu sehen.

Listing 2private static String[] stockSymbols = {"GOOG", "AAPL", "MSFT", "YHOO"}; private static void test01() { Arrays.stream(stockSymbols)//.parallel() ...

Java Magazin
Streams und blockierende Funktionalität

Einmal um den Block

Diesmal wollen wir uns genauer ansehen, wie parallele Streams mit blockierender Funktionalität umgehen und welche Möglichkeiten man als Stream-Nutzer hat, sie dabei zu beeinflussen.

Angelika Langer, Klaus Kreft


In der Softwarearchitektur gibt es das grundsätzliche Prinzip, den Durchsatz bei blockierender Funktionalität durch die Verwendung von mehreren parallelen Threads zu erhöhen. Typische Beispiele für blockierende Funktionalität sind synchrone Netzwerk-I/O über HTTP oder synchrone Datenbankzugriffe über JDBC. Verwendet man mehrere Threads, um diese blockierende Funktionalität parallel auszuführen, so lässt sich im Allgemeinen der Durchsatz steigern. Um solche Lösungen mit mehreren parallelen Threads zu implementieren, ist einiges an Design- und Implementierungsaufwand erforderlich. Außerdem braucht man im Bereich von Multi-Thread Programming ausreichendes Know-how, z. B. zum Umgang mit Threadpools oder zur Ergebnissynchronisation.

Jetzt, da parallele Streams ein Teil der JDKs sind, gibt es die Hoffnung, dass sich solche Lösungen deutlich einfacher implementieren lassen: Man übergibt einfach die blockierende Funktionalität in einem Lambda-Ausdruck an eine geeignete Stream-Operation eines parallelen Streams. Leider sind parallele Streams dafür nicht uneingeschränkt geeignet. Wo die Probleme einer solchen Lösung sind und welche zusätzlichen Möglichkeiten man als Stream-Nutzer hat, diese Probleme zu umgehen oder zu minimieren, wollen wir uns im vorliegenden Artikel im Detail ansehen.

Blockierende Funktionalität: ein Beispiel

Schauen wir uns zuerst ein konkretes Beispiel für blockierende Funktionalität an. Wir wollen uns mithilfe eines HTTP-Requests Informationen, Symbol, Aktienkurs, sowie Veränderung des Kurses zu dem Tickersymbol eines börsennotierten Unternehmens holen (Listing 1).

Listing 1public static String getStockInfo(String s) { try { URL yahoofinance = new URL("http://finance.yahoo.com/d/quotes.csv?s="+ s +"&f=sl1c");  URLConnection yc = yahoofinance.openConnection();  try (BufferedReader in = new BufferedReader(new InputStreamReader(yc.getInputStream()))) {  String result = in.readLine(); return result; } } catch (Exception e) { return null; }}

Diese blockierende Funktionalität übergeben wir in einem Lambda-Ausdruck an die map()-Operation eines Streams. Das heißt, in der map()-Operation wird das Tickersymbol (String) auf einen Ergebnis-String abgebildet, der Symbol, Aktienkurs sowie Veränderung des Kurses enthält. Die gesamte Stream-Verarbeitung ist in Listing 2 zu sehen.

Listing 2private static String[] stockSymbols = {"GOOG", "AAPL", "MSFT", "YHOO"}; private static void test01() { Arrays.stream(stockSymbols)//.parallel() ...

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