/***************************************************************/ /* Prof. Dr. Carsten Vogt */ /* FH Koeln, Fak. 07 / Nachrichtentechnik */ /* http://www.nt.fh-koeln.de/vogt */ /* */ /* wait(), notify(): */ /* Zwei Threads werden in eine Reihenfolge gebracht. Sie syn- */ /* chronisieren sich dafuer ueber ein Objekt, in dessen Metho- */ /* den sie wait() bzw. notify() aufrufen. */ /***************************************************************/ class SynchronObjekt { /* Synchronisationsobjekt, mit dessen Hilfe sich zwei Threads in eine Reihenfolge bringen. */ boolean stop; /* gibt an, ob der Nachfolgerthread warten muss */ /* Konstruktor: setzt "stop" auf true */ SynchronObjekt() { stop = true; } /* Die folgende Methode "warte()" versetzt den aufrufenden Thread in den Wartezustand, solange "stop" true ist. Der Uebergang in den Wartezustand erfolgt durch wait(); wait() muss in einer als synchronized deklarierten Methode eines Objekts benutzt werden. Die Benutzung einer while-Schleife, um die Wartebedingung zu testen, ist guter Programmierstil. Es kann durchaus vorkommen (wenn auch nicht in dieser speziellen Anwendung), dass ein Thread geweckt wird, ohne dass die spezielle Be- dingung, auf die er eigentlich wartet, erfuellt ist. Er sollte sie daher nochmals testen und ggf. erneut in den Wartezustand uebergehen. */ synchronized void warte() { while (stop) { try { wait(); /* wait() blockiert den aufrufenden Thread so lange, bis ein anderer Thread in einer anderen Methode dieses Objekts notify() oder notifyAll() aufruft. Das ist in diesem Fall der Thread, der die Methode "weiter()" ausfuehrt. */ } catch (InterruptedException E) { } } } /* Durch die Methode "weiter()" signalisiert der Vorgaenger- thread seinem Nachfolger, dass er weiterlaufen kann. Dies geschieht durch notify(), das wie wait() in einer als synchronized deklarierten Methode benutzt werden muss. */ synchronized void weiter() { stop = false; /* Benachrichtige per notify() einen wartenden Thread. */ notify(); } } /* Vorgaenger-Thread */ class Vorgaenger extends Thread { private SynchronObjekt obj; /* Objekt, ueber das der Thread sich synchronisiert */ Vorgaenger(SynchronObjekt o) { obj = o; } public void run() { try { System.out.println("Vorgaenger: Start"); /* Erst 4 Sekunden warten ... */ sleep(4000); /* ... und dann den Nachfolger benachrichtigen */ System.out.println("Vorgaenger: SYNCHRONISATIONSPUNKT ERREICHT"); obj.weiter(); System.out.println("Vorgaenger: Weiterlaufen"); sleep(2000); System.out.println("Vorgaenger: Ende"); } catch (InterruptedException E) { } } } /* Nachfolger-Thread */ class Nachfolger extends Thread { private SynchronObjekt obj; /* Objekt, ueber das der Thread sich synchronisiert */ Nachfolger(SynchronObjekt o) { obj = o; } public void run() { try { System.out.println("Nachfolger: Start"); System.out.println("Nachfolger: Warten am Synchronisationspunkt"); obj.warte(); System.out.println("Nachfolger: WEITERLAUFEN AM SYNCHRONISATIONSPUNKT"); sleep(3000); System.out.println("Nachfolger: Ende"); } catch (InterruptedException E) { } } } public class WaitNotify { /* Hauptprogramm */ public static void main(String[] args) { System.out.println(); SynchronObjekt sobj = new SynchronObjekt(); Vorgaenger t1 = new Vorgaenger(sobj); Nachfolger t2 = new Nachfolger(sobj); t1.start(); t2.start(); } }