480 likes | 559 Views
Parallelprogrammierung mit JAVA. Allgemeiner Hintergrund. Computer können heute immer mehrere Programme (quasi-) gleichzeitig ausführen. Viele Computer besitzen mehrere Prozessoren, z.T. mehrere Tausend, z.B. Cray T3E bzw. arbeiten im Cluster mit vielen anderen Rechnern zusammen.
E N D
Parallelprogrammierung mit JAVA EDV2 - 01 - Parallelprogrammierung
Allgemeiner Hintergrund • Computer können heute immer mehrere Programme (quasi-) gleichzeitig ausführen. • Viele Computer besitzen mehrere Prozessoren, z.T. mehrere Tausend, z.B. Cray T3E bzw. arbeiten im Cluster mit vielen anderen Rechnern zusammen. • Mutiuser-Betrieb:Programme mehrerer Nutzer laufen zur selben Zeit auf dem selben Rechner. Jeder Nutzer bekommt eigene Ressourcen zugeteilt. • Multitasking-Betrieb:Jeder Nutzer kann zur selben Zeit mehrere Programme laufen lassen. Jede Task bekommt eigene Ressourcen aus dem Pool des Nutzers und eine vollständig eigene Umgebung. • Multithreading-Betrieb:Ein Nutzer-Prozess kann sich in mehrere Threads (Minitasks) aufteilen. Alle Threads nutzen die Ressourcen des Elternprozesses und laufen in dessen Umgebung. EDV2 - 01 - Parallelprogrammierung
Threads in JAVA • Neben ADA ist JAVA die einzige Programmiersprache, die Threads direkt unterstützt. • JAVA besitzt Möglichkeiten Threads • zu erzeugen, • zu starten, • zu synchronisieren, • zu beenden, • zu verwalten • sowie zwischen Threads zu kommunizieren EDV2 - 01 - Parallelprogrammierung
Die Klasse Thread • Klassen, die als Thread gestartet werden sollen, müssen von der Klasse Thread abgeleitet werden und die Methodepublic void run()überschreiben. • Ein Thread wird durch Aufruf vonname.start()gestartet. Die Methode start ruft anschließend die Methode run auf, die dann die eigentliche Arbeit des Threads erledigt. • Das gesamte Programm wird beendet, wenn alle Threads fertig sind • Konstruktoren:public Thread()public Thread(String name)erzeugt ein Threadobjekt mit dem Namen name bzw. „Thread-nnn“ EDV2 - 01 - Parallelprogrammierung
Beispiel1 public class Beispiel1 extends Thread { public void run() //Ausgeben der Zahlen 0,1,2,... { int i = 0; while (true) System.out.println(i++); } } public class Listing1 { public static void main(String[] args) { Beispiel1 t = new Beispiel1(); //Erzeugen des Thread-Objektes t.start(); //Thread starten } } EDV2 - 01 - Parallelprogrammierung
Nachdem der Thread t gestartet wurde, ist main fertig. Das gesamte Programm wartet auf die Beendigung des Threads. Dieser wird aber nie fertig. Das Programm muss also von außen unterbrochen werden. • Es können ein Attributprivate boolean cancelled = false;und eine Methodepublic void cancel() {cancelled=true;}definiert werden. • Während run abgearbeitet wird, wird cancelled geprüft und ggf. run beendet. • Problem: cancelled muss oft genug abgefragt werden, um eine schnelle Reaktion auf cancel() zu garantieren. cancelled darf aber nicht zu oft abgefragt werden, um die Performance nicht zu stark zu verschlechtern. • Es muss garantiert werden, dass die Daten immer konsistent bleiben! EDV2 - 01 - Parallelprogrammierung
Beispiel2 public class Beispiel2 extends Thread { private boolean cancelled = false; public void cancel() {cancelled=true;} public void run() //Ausgeben der Zahlen 0,1,2,... { int i = 0; while (! cancelled) System.out.println(i++); } } public class Listing2 { public static void main(String[] args) { Beispiel2 t = new Beispiel2(); //Erzeugen des Thread-Objektes t.start(); //Thread starten try {Thread.sleep(1000);} catch (InterruptedException ie) {} t.cancel(); } } EDV2 - 01 - Parallelprogrammierung
interrupt, interrupted, isInterrupted • public void interrupt()markiert einen Thread als abgebrochen. • public static boolean interrupted()fragt den interrupt-Status des aktuellen Threads ab und setzt ihn anschließend wieder zurück. • public boolean isInterrupted()fragt den interrupt-Status ab EDV2 - 01 - Parallelprogrammierung
Beispiel3 public class Beispiel3 extends Thread { public void run() //Ausgeben der Zahlen 0,1,2,... { int i = 0; while (! isInterrupted()) { System.out.println(i++); try{sleep(100);} catch(InterruptedException ie){interrupt();} } } } public class Listing3 { public static void main(String[] args) { Beispiel3 t = new Beispiel3(); //Erzeugen des Thread-Objektes t.start(); //Thread starten try {Thread.sleep(1000);} catch (InterruptedException ie) {} t.interrupt(); } } EDV2 - 01 - Parallelprogrammierung
Methoden der Klasse Thread • public static void sleep(long millis)throws InterruptedException public static void sleep(long millis, int nanos) throws InterruptedException unterbricht den aktuellen Thread für millis/1000+nanos/1000000 SekundenFalls der Thread in dieser Zeit unterbrochen wird, wird die InterruptedException ausgelöst. • public final boolean isAlive()fragt, ob der Thread noch aktiv ist. • public final void join() throws InterruptedExceptionjoin() wartet auf die Beendigung des Threads. Falls der wartende Thread unterbrochen wird, wird die InterruptedException ausgelöst. • public final void join(long millis) throws InterruptedExceptionpublic final void join(long millis, int nanos) throws InterruptedExceptionwartet maximal millis/1000+nanos/1000000 Sekunden EDV2 - 01 - Parallelprogrammierung
Beispiel4 public class Beispiel4 extends Thread { public void run() //Ausgeben der Zahlen 0,1,2,... { int i = 0; while (i<20) { System.out.println(i++); try{sleep(100);} catch(InterruptedException ie){} } } } public class Listing4 { public static void main(String[] args) { Beispiel4 t = new Beispiel4(); //Erzeugen des Thread-Objektes t.start(); //Thread starten try{ System.out.println("Thread gestartet"); t.join(1000); System.out.println("nach einer Sekunde"); t.join();} catch(InterruptedException ie){} } } EDV2 - 01 - Parallelprogrammierung
Daemon-Threads • Daemon-Threads werden bei der Beendigung des Gesamtprogramms nicht berücksichtigt. Daemon-Threads werden also beendet, wenn alle nicht-Daemon-Threads fertig sind. • public final void setDaemon(boolean on)markiert den Thread als Daemon-Thread. setDaemon muss vor dem Start des Threads aufgerufen werden. EDV2 - 01 - Parallelprogrammierung
Beispiel5 public class Beispiel1 extends Thread { public void run() //Ausgeben der Zahlen 0,1,2,... { int i = 0; while (true) System.out.println(i++); } } public class Listing5 { public static void main(String[] args) { Beispiel1 t = new Beispiel1(); //Erzeugen des Thread-Objektes t.setDaemon(true); //Thread als Daemon markieren t.start(); //Thread starten try{Thread.sleep(100);} catch(InterruptedException ie){} } } EDV2 - 01 - Parallelprogrammierung
Das Interface Runnable • Zuweilen ist es nicht möglich eine Klasse von Thread abzuleiten. Z.B. wenn die Klasse von einer anderen Klasse (z.B. JApplet oder JFrame) abgeleitet werden muss. • Dann kann man die Klasse von dem Interface Runnable ableiten und muss dann die Methode run() implementieren. • Die Klasse Thread hat dazu weiter Konstruktoren:public Thread(Runnable target) public Thread(Runnable target, String name)Es wird ein Thread-Objekte erzeugt, das von einem Objekt target abgeleitet wird, das das Interface Runnable implementiert. EDV2 - 01 - Parallelprogrammierung
Beispiel6 public class Beispiel6 implements Runnable { public void run() //Ausgeben der Zahlen 0,1,2,... { int i = 0; while (i<20) { System.out.println(i++); try{Thread.sleep(100);} catch(InterruptedException ie){} } } } public class Listing6 { public static void main(String[] args) { Thread t = new Thread(new Beispiel6()); t.start(); try{ System.out.println("Thread gestartet"); t.join(1000); System.out.println("nach einer Sekunde"); t.join();} catch(InterruptedException ie){} } } EDV2 - 01 - Parallelprogrammierung
Parallelisierung von QuickSort public class QuickSort { public static void sort(double[] v){ sort(v, 0, v.length-1); } public static void sort(double[] a, int l, int r){ int i = 0; int j = 0; double x = 0; double h = 0; i = l; j = r; x = a[(l+r)/2]; do { while (a[i] < x) { i++; } while (x < a[j]) { j--; } if (i <= j) { h = a[i]; a[i] = a[j]; a[j] = h; i++; j--; } } while (i <= j); if (l < j) sort(a, l, j); if (i < r) sort(a, i, r); } } EDV2 - 01 - Parallelprogrammierung
Probleme • QuickSort ist ein typisches Beispiel, bei dem das ganze Programm erst zu Ende ist, wenn alle Threads ihre Arbeit beendet haben. Auf alle erzeugten Threads muss mit join() gewartet werden. • Die Klasse QuickSort muss von Thread abgeleitet werden:public class QuickSort extends Thread • Die QuickSort-Methode wurde bisher mit Parametern aufgerufen. Die Methode run ist aber ohne Parameter! • Die einzelnen Threads sind Objekte. Man kann nicht mit statischen Methoden arbeiten, sondern muss für jeden Thread ein neues Objekt erzeugen, dessen start-Methode aufgerufen werden muss. • Die erforderlichen Parameter können nur beim Konstruktor übergeben werden.Wir müssen entsprechende Konstruktoren schreiben. EDV2 - 01 - Parallelprogrammierung
private double[] a; private int l; private int r; QuickSort(double[] a, int l, int r){ this.a=a; this.l=l; this.r=r; } QuickSort(double[] a){ this(a, 0, a.length-1); } public void run(){ sort(a, l, r); } EDV2 - 01 - Parallelprogrammierung
Bisher ist an der eigentlichen Methode sort nichts geändert. Sie kann wie bisher als statische Methode aufgerufen werden. • Zusätzlich gibt es nun die Möglichkeit die Sortierung des Feldes a über ein Objekt und dessen Methode run() oder start() zu starten:QuickSort qs = new QuickSort(a);qs.run(); oder qs.start(); • Es wird aber noch nicht parallelisiert! • Wo kann parallelisiert werden?if (l < j) sort(a, l, j);if (i < r) sort(a, i, r); • Wird ersetzt durch:QuickSort tl = null;QuickSort tr = null;if (l < j) {tl = new QuickSort(a,l,j); tl.start();}if (i < r) {tr = new QuickSort(a,i,r); tr.start();}if (tl!=null) tl.join();if (tr!=null) tr.join(); EDV2 - 01 - Parallelprogrammierung
Problem: Zu viele Threads • In dieser Realisierung werden letztendlich ca. doppelt so viele Threads erzeugt, wie das Feld Elemente hat. Fast alle sind sehr klein, sodass der Overhead unverhältnismäßig groß wird. Man muss dafür sorgen, dass nicht zu viele kleine Threads erzeugt werden. • Steuerungsmöglichkeit über die Länge des zu sortierenden Abschnittes. Einführung eines Parameters c, der die Mindestlänge eines in einem neuen Thread zu sortierenden Abschnittes beschreibt. Ist die Länge kleiner als c wird kein neuer Thread erzeugt, sondern seriell weitergearbeitet. • Der Parameter c ist in die Attributliste, in die Paramterliste der Konstruktoren und der sort-Methode aufzunehmen EDV2 - 01 - Parallelprogrammierung
private double[] a; private int l; private int r; private int c; QuickSort(double[] a, int l, int r, int c){ this.a=a; this.l=l; this.r=r; this.c=c; } QuickSort(double[] a){ this(a, 0, a.length-1, a.length); } public void run(){ sort(a, l, r, c); } EDV2 - 01 - Parallelprogrammierung
try { Thread tl=null, tr=null; if ( (l+c<j) & (i+c<r)) { tl = new QuickSort(a, l, j, c); tl.start(); tr = new QuickSort(a, i, r, c); tr.start(); System.out.print("activeCount = "+Thread.activeCount()); } else { if (l < j) sort(a, l, j, c); if (i < r) sort(a, i, r, c); } if (tl != null) tl.join(); if (tr != null) tr.join(); } catch (InterruptedException e){} EDV2 - 01 - Parallelprogrammierung
Verwaltung von Threads • Threadgroups dienen der Organisation von Threads. • Threads können in Gruppen zusammengefasst werden. • Threadgroups können Threads und Threadgroups enthalten. Es gibt eine Hierarchie von Threadgroups. • Es kann mehrere Threadgroups nebeneinander geben. • Man kann ganze Threadgroups als Daemon definieren. • Man kann alle Threads einer Gruppe bestimmen. • Man kann die maximale Priorität einer Threadgroup festlegen. EDV2 - 01 - Parallelprogrammierung
Die Klasse ThreadGroup • Konstruktoren:public ThreadGroup(String name) public ThreadGroup(ThreadGroup parent, String name) • public final void setDaemon(boolean daemon)definiert die ThreadGroup als Daemon, d.h. alle Threads der Gruppe sind Daemons • public final void setMaxPriority(int pri)setzt die maximale Priorität der Threads der Gruppe • public int activeCount()gibt die Anzahl der in der Gruppe aktiven Threads aus • public int activeGroupCount() gibt die Anzahl der in der Gruppe aktiven ThreadsGroup´s aus • public int enumerate(Thread[] list)gibt ein Feld aller aktiven Threads der Gruppe aus • public int enumerate(ThreadGroup[] list) gibt ein Feld aller aktiven ThreadsGroup´s der Gruppe aus EDV2 - 01 - Parallelprogrammierung
Die Klasse ThreadGroup • public final void interrupt()ruft interrupt-Methode alle aktiven Threads der Gruppe auf • public void uncaughtException(Thread t, Throwable e)wird von der JVM aufgerufen, wenn von einem Thread der Gruppe die Ausnahme e ausgelöst wird EDV2 - 01 - Parallelprogrammierung
Anwendung bei QuickSort • Problem: jeder Thread, der neue Threads erzeugt hat, wartet nach Erzeugung der Threads nur noch auf deren Ende um sich am nach Beendigung der erzeugten Thread selbst zu beenden. Dadurch entstehen viele aktive Threads (ca. 50%), die eigentlich nicht mehr aktiv zu sein brauchten. • Aktive Threads blockieren Systemressourcen. • Lösungsmöglichkeit: • Einrichtung einer ThreadGroup und Erzeugung aller QuickSort-Threads in dieser Gruppe. • Starten des QuickSort-Programms als Thread. • Anschließend warten bis kein aktiver Thread mehr in der Gruppe ist. EDV2 - 01 - Parallelprogrammierung
public static ThreadGroup tg = new ThreadGroup("QuickSort"); new QuickSort(a, 0, a.length-1,c).start(); int tgn=0; while ( (tgn=tg.activeCount()) > 0) { try{Thread.sleep(100);} catch(InterruptedException ie){} } EDV2 - 01 - Parallelprogrammierung
Synchronisieren von Threads • Bei der parallelen Abarbeitung von Thread kann es zu Konflikten beim Zugriff auf gemeinsam genutzte Daten kommen. • Beispiel: SimpleBankEs sollen Überweisungen zwischen drei Konten durch gleichzeitig arbeitende Angestellte vorgenommen werden. EDV2 - 01 - Parallelprogrammierung
Modellierung eines Kontos public class Konto { int kontostand; public Konto(int kontostand) { this.kontostand=kontostand; } void add(int wert) { int neuerWert=kontostand; try { Thread.sleep((int)(Math.random()*100)); } catch (InterruptedException e) { } neuerWert+=wert; kontostand=neuerWert; } } EDV2 - 01 - Parallelprogrammierung
Modellierung der Bank public class SimpleBank { static Konto [] konten = {new Konto(30),new Konto(50),new Konto(100)}; public void ueberweisung(int von, int nach, int betrag) { konten[von].add(-betrag); konten[nach].add(betrag); } public void kontostand() { for (int i=0;i<konten.length;i++) { System.out.println("Konto "+i+": "+konten[i].kontostand); } } } EDV2 - 01 - Parallelprogrammierung
Modellierung des Angestellten public class Angestellter extends Thread { SimpleBank bank; int von, nach, betrag; public Angestellter(SimpleBank bank, int von, int nach, int betrag) { this.bank=bank; this.von=von; this.nach=nach; this.betrag=betrag; } public void run() { bank.ueberweisung(von, nach, betrag); bank.kontostand(); } } EDV2 - 01 - Parallelprogrammierung
Simulation der Überweisungen public class SimpleBankDemo { public static void main(String[] args) throws Exception { SimpleBank b = new SimpleBank(); Angestellter A1, A2, A3; b.kontostand(); for (int i=0;i<100;i++) { A1 = new Angestellter(b, 0, 1, 20); A2 = new Angestellter(b, 1, 2, 20); A3 = new Angestellter(b, 2, 0, 20); A1.start(); A2.start(); A3.start(); A1.join(); A2.join(); A3.join(); } b.kontostand(); } } EDV2 - 01 - Parallelprogrammierung
Resultat • Bei jedem Test ergeben sich andere Resultate. • Ursache: • Bei der Überweisung wird erst der alte Kontostand, dann eine zufällige Zeit gewartet und dann erst der neue Kontostand berechnet und gespeichert. • In der Wartezeit kann ein anderer Angestellter den alten Kontostand lesen und eine Kontoänderung durchführen. • Lösung: • Es muss verhindert werden, dass ein Konto, das von einem Angestellten geändert wird, von einem weiteren geändert werden kann. • Dazu muss verhindert werden, dass die Methode add der Klasse Konto von mehreren anderen Programmen gleichzeitig benutzt wird. • Das wird erreicht durch das Schlüsselwort synchronized vor der Methodendeklaration. EDV2 - 01 - Parallelprogrammierung
Modellierung eines Kontos public class Konto { int kontostand; public Konto(int kontostand) { this.kontostand=kontostand; } synchronized void add(int wert) { int neuerWert=kontostand; try { Thread.sleep((int)(Math.random()*100)); } catch (InterruptedException e) { } neuerWert+=wert; kontostand=neuerWert; } } EDV2 - 01 - Parallelprogrammierung
Synchronisation durch Monitore • synchroinzed kann auch vor einem Block stehen:synchronized(objekt){...} • Das objekt heißt Sperre (Lock). • Durch diese Form des sysnchronized-Blockes wird verhindert, dass der Block von zwei Threads betreten wird, die die selbe Sperre besitzen. Synchronized-Blöcke können geschachtelt werden. • Spezialfälle: • objekt==this : es wird auf das aktuelle Objekt synchronisiert, d.h. z.B. die add-Methode eines Kontos, darf nur einmal gleichzeitig aktiv sein. Andere Konten können aber parallel geändert werden. • objekt==getClass() : der synchronisierte Block darf nur von einem Objekt dieser Klasse betreten werden. Günstig bei der Modifikation statischer Attribute. • objekt==Thread.currentThread().getThreadGroup() : der synchronisierte Block darf nur von einem Objekt der selben ThreadGroup betreten werden. EDV2 - 01 - Parallelprogrammierung
Modellierung eines Kontos public class Konto { public static int count=0; int kontostand; public Konto(int kontostand){this.kontostand=kontostand;} void add(int wert) { synchronized(this){ int neuerWert=kontostand; try{Thread.sleep((int)(Math.random()*100));} catch (InterruptedException e){} neuerWert+=wert; kontostand=neuerWert; } synchronized(getClass()){ int c=count; try{Thread.sleep((int)(Math.random()*10));} catch (InterruptedException e){} count=++c; } } } EDV2 - 01 - Parallelprogrammierung
Synchronisierung mit wait / notify • wait und notify sind Methoden der Klasse Object. • Sie dürfen nur innerhalb von synchronized-Methoden aufgerufen werden. • public final void wait() throws InterruptedException • public final void wait(long timeout) throws InterruptedException • public final void wait(long timeout, int nanos) throws InterruptedException • wait versetzt den aktuellen Thread in den Wartezustande, bis entweder die Zeit abgelaufen ist, ihn ein anderer Thread in dieser Zeit aufgeweckt hat oder er in dieser Zeit von außen beendet wurde. • public final void notify() • notify weckt einen anderen Thread, der auf das Freiwerden des aktuellen Objektes als Sperre wartet. EDV2 - 01 - Parallelprogrammierung
Beispiel : Lager • Es soll ein Lager modelliert werden. • Das Lager hat eine feste Zahl von Stellplätzen. • In unbestimmten Abständen kommen Produzenten, um ein Produkt einzulagern und Verbraucher, um ein Produkt abzuholen. • Der Produzent muss warten, wenn das Lager voll ist, bis ein Verbraucher kommt. • Der Verbraucher muss warten, wenn das Lager leer ist bis ein Produzent kommt. • „synchronized“ reicht nicht, da damit nur das gleichzeitige Betreten des Lagers durch mehrere Produzenten bzw. Verbraucher verhindert werden kann. • Lösung: • Verbraucher ruft wait() auf, solange das Lager leer ist. • Produzent ruft wait() auf, solange das Lager voll ist. • Verbraucher und Produzent rufen nach beendeter Arbeit notify auf, einen wartenden Verbraucher oder Produzenten zu aktivieren. EDV2 - 01 - Parallelprogrammierung
Modellierung des Lagers public class Lager{ private int maxValues = 10; private float [] values=new float[maxValues]; private int nextValue = 0; public synchronized void put(float value) { while (nextValue==maxValues) try{wait();}catch (InterruptedException ie){} values[nextValue]=value; System.out.println("put : "+value+" auf Platz "+nextValue); nextValue++; notify(); } public synchronized float get(){ while (nextValue==0) try{wait();}catch (InterruptedException ie){} nextValue--; float value = values[nextValue]; System.out.println("get : "+value+" von Platz "+nextValue); notify(); return value; } } EDV2 - 01 - Parallelprogrammierung
Modellierung des Verbrauchers public class Verbraucher extends Thread { Lager lager; public Verbraucher(Lager lager) { this.lager=lager; } public void run() { try{sleep((int)(Math.random()*1000));} catch(InterruptedException ie){} lager.get(); } } EDV2 - 01 - Parallelprogrammierung
Modellierung des Produzenten public class Produzent extends Thread { Lager lager; public Produzent(Lager lager) { this.lager=lager; } public void run() { try{sleep((int)(Math.random()*500));} catch(InterruptedException ie){} lager.put((float)Math.random()); } } EDV2 - 01 - Parallelprogrammierung
Modellierung des Gesamtprozesses public class LagerDemo { public static void main(String[] args) { Lager lager = new Lager(); for (int i=0;i<50;i++) { Verbraucher v = new Verbraucher(lager); v.start(); } for (int i=0;i<50;i++) { Produzent p = new Produzent(lager); p.start(); } } } EDV2 - 01 - Parallelprogrammierung
Verbindung von Threads über Pipes • Es seien zwei Threads zu programmieren, wobei ein Thread Daten produziert und der andere Thread diese Daten nach dem FIFO-Prinzip verarbeitet. • Zur Lösung dieses Problems bieten sich Pipes an. • Pipes sind Datenströme, die gleichzeitig geschrieben und gelesen werden können, wobei die Daten die zuerst geschrieben werden auch wieder gelesen werden. • Pipes besitzen einen Puffer. Ist der Puffer voll, wird der schreibende Thread angehalten, bis wieder Platz frei ist. Ist der Puffer leer, wartet der lesende Thread, bis wieder Daten verfügbar sind. • Es gibt PipedInputStream/PipedOutputStream sowie PipedReader/PipedWriter. EDV2 - 01 - Parallelprogrammierung
Die Klassen PipedXXX • Die Klassen sind von den entsprechenden Klassen aus java.io abgeleitet, d.h. PipedXXX extends XXX, d.h. sie können als Kern für BufferedXXX, ObjectXXX u.s.w. genutzt werden. • Konstruktoren: • PipedInputStream(PipedOutputStream src) • PipedOutputStream(PipedInputStream snk) • Methoden: • public void connect(PipedOutputStream src) throws IOException • public void connect(PipedInputStream snk) throws IOException EDV2 - 01 - Parallelprogrammierung
Beispiel: Datenproduzent import java.io.*; public class Produzent extends Thread{ BufferedWriter out; public Produzent(Writer out){ if (out instanceof BufferedWriter) this.out=(BufferedWriter)out; else this.out=new BufferedWriter(out); } public void run(){ try { for (int i=0;i<20;i++) { sleep((int)(Math.random()*1000)); System.out.println(i+" : "); out.write("Das ist Satz Nr. "+i); out.newLine(); out.flush(); } out.write("ende\n"); } catch(Exception e){} }} EDV2 - 01 - Parallelprogrammierung
Beispiel: Datenverbraucher import java.io.*; public class Verbraucher extends Thread{ BufferedReader in; public Verbraucher(Reader in){ if (in instanceof BufferedReader) this.in=(BufferedReader)in; else this.in=new BufferedReader(in); } public void run(){ try { for (int i=0;;i++) { String line=in.readLine(); System.out.println(line); if (line.equals("ende")) return; } } catch(Exception e){} } } EDV2 - 01 - Parallelprogrammierung
Beispiel: Kopplung import java.io.*; public class TestPipe { public static void main(String[] args) throws Exception { PipedWriter out = new PipedWriter(); PipedReader in = new PipedReader(out); Produzent p = new Produzent(out); Verbraucher v = new Verbraucher(in); v.start(); p.start(); } } EDV2 - 01 - Parallelprogrammierung