Motivation. Informatik B - Objektorientierte Programmierung in Java. Vorlesung 20: Threads. Inhalt. Ein Beispiel zur Motivation

Ähnliche Dokumente
Dr. Monika Meiler. Inhalt

Parallele Prozesse. Prozeß wartet

5. Threads, Serverprozesse und Benachrichtigungen

Praktikum aus Softwareentwicklung 2, Stunde 5

Nebenläufigkeit mit Java

Vorlesung Informatik II

Parallele Prozesse Prozeß Parallele Prozesse verzahnte Prozesse Nebenläufige Prozesse: Threads Vorlesung Software-Entwicklung / Folie 131 Ziele:

Informatik B - Objektorientierte Programmierung in Java. Vorlesung 21: Threads 2. Inhalt

Prozesse. Prozesse sind Programme. Prozesse können aus Unterprozessen bestehen. Prozesshierarchie Unterprozesse Threads

Vorlesung Informatik II

Nebenläufige Programmierung in Java: Threads

2.2 Prozesse in Java

Java I Vorlesung Nebenläufigkeit

Nebenläufige Programmierung I

Ausnahmebehandlung in Java

Synchronisation in Java. Invisible Web

Thread-Synchronisation in in Java. Threads Wechselseitiger Ausschluss Bedingte Synchronisation Beispiel: Warteschlangen

Parallele und funktionale Programmierung Wintersemester 2015/ Übung Abgabe bis , 10:00 Uhr

Ausgewählte Implementierungsprobleme

Dezentrale Kontrolle: Aktive Objekte. Aktive Objekte Die Klasse AnimatorThread Aktivierung Objekte beobachten Die Java-Klasse Thread

Neben der Verwendung von Klassen ist Vererbung ein wichtiges Merkmal objektorientierter

Objektorientierte Programmierung OOP Objektorientierte Programmierung (OOP) mit Java

Threading. Arthur Zaczek. Aug 2015

Universität Potsdam Institut für Informatik Sommersemester Programmierung. Lehrblatt Woche 11

Thread-Konzept in objektorientierten Programmiersprachen. Threads. Threads in Java

Programmierung mit Threads in Java

Soll die Programm-Ausführung nicht beendet werden, muss der Fehler abgefangen werden. NumberFormatException

12. Threads in Java. Sequentielle Abarbeitung (2) Beispiel: Thread (1) Sequentielle Abarbeitung (1)

Beispiel für überladene Methode

Nebenläufigkeit mit Java

Java Concurrency Utilities

Übung zu Grundlagen der Betriebssysteme. 10. Übung

Betriebssysteme G: Parallele Prozesse (Teil A: Grundlagen)

Grundlagen der Fehlerbehandlung. Informatik B - Objektorientierte Programmierung in Java. Vorlesung 06: Ausnahme- und Fehlerbehandlung in Java.

Nebenläufigkeit in Java. Prof. Dr. Margarita Esponda

Javakurs für Anfänger

16. Parallelität: Threads

Repetitorium Informatik (Java)

Kapitel 8. Programmierkurs. Methoden. 8.1 Methoden

Verteilte Systeme. 2. Die Client-Server-Beziehung und daraus resultierende Techniken. 2.2 Nebenläufigkeitstechniken in Java

Problemstellung. Informatik B - Objektorientierte Programmierung in Java. Vorlesung 24: Reflection 1. IDE und automatische Tests.

Überblick. Verteilte Systeme - Übung. Was ist ein Thread? Threads in Java. Multithreading in Java Threads Synchronisation Koordinierung

Kapitel 9. Programmierkurs. Attribute von Klassen, Methoden und Variablen. 9.1 Attribute von Klassen, Methoden und Variablen

Durch die Teil-von-Beziehung soll ausgedrückt werden, dass ein Objekt A als (physikalischer) Teil eines Objekts B angesehen wird. Insbesondere kann ei

Vererbung, Polymorphie

2 Eine einfache Programmiersprache

Einführung in die Programmierung für Nebenfach Medieninformatik. Beat Rossmy, Michael Kirsch

Versuchsziele Konzepte der parallelen Programmierung am Beispiel von Threads anwenden können. Einbau von Kontrollmechanismen mittels Semaphore.

Objektorientierte Programmierung und Klassen

Arbeitsblätter für die Lehrveranstaltung OOP JAVA 4

Javakurs FSS Lehrstuhl Stuckenschmidt. Tag 3 - Objektorientierung

Vererbung. Gerd Bohlender. Institut für Angewandte und Numerische Mathematik. Vorlesung: Einstieg in die Informatik mit Java 23.5.

Programmieren II. Innere Klassen. Heusch 10, Ratz 5.2.1, Institut für Angewandte Informatik

Einstieg in die Informatik mit Java

VS4 Slide 1. Verteilte Systeme. Vorlesung 4 vom Dr. Sebastian Iwanowski FH Wedel

Institut für Programmierung und Reaktive Systeme. Java 6. Markus Reschke

Multi-Threading. Ralf Abramowitsch Vector Informatik GmbH

Einstieg in die Informatik mit Java

FH D. Objektorientierte Programmierung in Java FH D FH D. Prof. Dr. Ing. André Stuhlsatz. Wiederholung: Gerüstbeispiel. Vererbungshierarchie: Typ 0

8.6 Visualisierung der Sortieralgorithmen

Threads In dieser Übung beschäftigen wir uns mit der Realisierung von Threads in Java.

Nebenläufige Programmierung I

Zur Erinnerung: Threads. Threadverwaltung. Threads: Prioritäten. Beispiel Flugbuchungsprogramm. Nichtdeterminismus

Klausur Software-Entwicklung März 01

3 Objektorientierte Konzepte in Java

EINFÜHRUNG IN DIE PROGRAMMIERUNG

Schritt 1 - Ein Spielfeld

Einstieg in die Informatik mit Java

6. Tutorium zu Softwaretechnik I

Einführung in die Programmierung Blockkurs Java

Nebenläufigkeit in Java

Klausurvorbereitung VS1 (Prof. Brecht) (B0rg Edition)

Universität Augsburg, Institut für Informatik Sommersemester 2001 Prof. Dr. Martin Ester 08. Oktober Klausur II

Klausur Software-Entwicklung September 00

Parallele und verteilte Anwendungen in Java

Beispiele für Ausdrücke. Der imperative Kern. Der imperative Kern. Imperativer Kern - Kontrollstrukturen. Deklarationen mit Initialisierung

Einstieg in die Informatik mit Java

12 Abstrakte Klassen, finale Klassen und Interfaces

Objektorientierte Programmierung. Kapitel 22: Aufzählungstypen (Enumeration Types)

Kapitel 9: Klassen und höhere Datentypen. Klassen und höhere. Objekte, Felder, Methoden. Küchlin/Weber: Einführung in die Informatik

3 Objektorientierte Konzepte in Java

Sommersemester Implementierung I: Struktur

7. Übung Informatik II - Objektorientierte Programmierung

Funktionale und Objekt-Orientierte Programmierkonzepte

Kapitel 10. Programmierkurs. Grundlagen von Exceptions Behandlung von Exceptions

Universität Karlsruhe (TH)

Java Real-Time Specification

Verteilte Systeme CS5001

Beispiel: Methode mit einem Fehler. Diese Methode wird problematisch, wenn von außen eine Dauer von 0 Sekunden angegeben wird, etwa im Aufruf

Sequentielle Programm- / Funktionsausführung innerhalb eines Prozesses ( thread = Ausführungsfaden )

Institut für Programmierung und Reaktive Systeme 17. Juli Programmieren II. Übungsklausur

3. Klassen Statische Komponenten einer Klasse. Klassenvariablen

Objektorientierte Programmierung Studiengang Medieninformatik

Algorithmen implementieren. Implementieren von Algorithmen

Institut für Informatik. Endterm Klausur zu Informatik I 20. Februar 2010

Silke Trißl Wissensmanagement in der Bioinformatik. Objektorientierte Programmierung (OOP) Vorstellung wie in der realen Welt: Farbe Hubraum Tank...

1 Abstrakte Klassen, finale Klassen und Interfaces

Javaprogrammierung unter Notes

Systeme I: Betriebssysteme Kapitel 4 Prozesse. Wolfram Burgard

Einstieg in die Informatik mit Java

Transkript:

Universität Osnabrück 1 Motivation 3 - Objektorientierte Programmierung in Java Führt ein Applet eine lange Berechnung aus, so erfolgt keine Reaktion auf die Betätigung des Stop-Buttons am Browser bzw. Appletviewer. Vorlesung 20: Threads SS 2004 Prof. Dr. F.M. Thiesing, FH Dortmund Inhalt 2 Ein Beispiel zur Motivation 4 Threads Ein Beispiel zur Motivation Parallelität, Nebenläufigkeit, Prozess, Thread Thread vs. Prozess Typische Einsatzgebiete von Threads Erzeugung von Threads Beendung von Threads Das Interface Runnable Synchronisation Siehe: Krüger: Handbuch der Javaprogrammierung, www.javabuch.de, Kapitel 22. import java.applet.*; import java.awt.*; public class DemoOhneThreads extends Applet { String s; public void start() { long n; for ( int j=1; j<1000; j++) { for ( int i=1; i<1000; i++) { for ( int k=1; k<1000; k++) { n = k + i + j; if ((j % 100) == 0) {System.out.print(j+" "); System.out.flush(); System.out.println("start: finished"); public void paint( Graphics g ) { String s; g.setcolor( Color.blue ); s = new String( "paint: done" ); g.drawstring( s, 10, 20); Die laufende Berechnung ist nicht unterbrechbar, weil die Programmkontrolle nicht abgegeben wird.

Nebenläufigkeit 5 Thread 7 Java hat das Konzept der Nebenläufigkeit innerhalb der Sprache implementiert. Mit Nebenläufigkeit bezeichnet man die Eigenschaft eines Systems, zwei oder mehr Vorgänge gleichzeitig oder quasi-gleichzeitig ausführen zu können. Ein Thread (engl. für Faden) stellt eine nebenläufige Ausführungseinheit innerhalb genau eines Prozesses dar, die parallel zu anderen Threads laufen kann. Ein Thread ähnelt damit einem Prozess, arbeitet aber auf einer feineren Ebene. Prozess 6 Bemerkungen 8 Ein Prozess bezeichnet ein Programm in Ausführung mit seinen dafür notwendigen betriebssystemseitigen Datenstrukturen und zugeordneten Eigenschaften (z.b. Stack- und Programmzähler, Prozesszustand sowie Eigenschaften der Speicher- und Dateiverwaltung). Ein Prozess wird durch das Betriebssystem als eigenständige Instanz - in der Regel unabhängig und geschützt von anderen - ausgeführt. Multitaskingsysteme (wie UNIX und neuere Generationen der Windows- Familie) gestatten die (quasi-)parallele Prozessausführung. Threads haben viele der prozesstypischen Eigenschaften, wie Zustand, Programmzähler etc. Den Hauptunterschied zu voll entwickelten Prozessen bildet der zwischen allen Threads eines Prozesses geteilte Speicher. Gleichzeitig besitzt jeder Thread seinen eigenen lokalen Speicherbereich in dem u.a. die lokalen Variablen verwaltet werden. Aus diesen Gründen werden Threads oft auch als leichtgewichtige Prozesse bezeichnet. Alle Threads bewegen sich im Ausführungskontext des erzeugenden Prozesses. In Multithreading-Systemen besitzt jeder ablaufende Prozess mindestens einen Thread, der den Kontrollfluss realisiert.

Threads 9 Threads als Teil von Prozessen 11 Ein Thread hat gewisse Ähnlichkeit mit einem Prozess: er kann vom Scheduler angehalten und fortgesetzt werden er kann ohne CPU-Belastung auf Eingabe warten: der Thread wird gestoppt wenn die Eingabe kommt, wird er vom Scheduler fortgesetzt Mit Hilfe des Threads wird ermöglicht, dass andere Anwendungsteile reagieren können: in regelmäßigen Abständen stoppt der Scheduler einen Thread und setzt einen anderen Prozess (Thread) fort nach einer gewissen Zeit wird der gestoppte Thread wieder aktiviert Threads sind in Prozesse eingebettet, d.h. Teile von Prozessen. Jeder Prozess besteht aus mindestens einem Thread. Threads eines Prozesses besitzen einen gemeinsamen Speicherbereich. Dies führt zu leichter Kommunikation zwischen den Threads eines Prozesses Koordinierungsprobleme Zusammenhang zwischen Prozess und Thread 10 Typische Einsatzgebiete von Threads 12 Der Prozess wird in der Regel erst mit dem Ende des letzten Threads beendet. Bevor auf Details eingegangen wird, hier zunächst typische Einsatzgebiete von Threads: zur Vermeidung von Blockaden der Benutzerschnittstelle; dann kann eine Anwendung weiterhin auf Benutzereingaben reagieren um nach Ablauf einer bestimmten Zeit ein Ereignis auszulösen. Beispiel: eine Bilderfolge in einem Applet, die im Sekundentakt verändert wird zur Parallelisierung einer Anwendung auf mehrere Prozessoren; dann kann in Mehrprozessorsystemen für jeden Prozessor ein Thread gestartet werden; der parallel verarbeitbare Programmteil wird in einen Thread verpackt zur Bedienung von blockierenden Schnittstellen. Beispiel: Warten auf Netzwerkverbindungen (siehe kommende Vorlesung)

Zu klärende Probleme 13 Erzeugung von Threads 15 Wie werden Threads vereinbart? Wie werden Threads gestartet? Wie werden Threads gestoppt? Wie erfolgt die Koordinierung? Thread stellt die Basismethoden zur Erzeugung, Kontrolle und zum Beenden von Threads zur Verfügung. Um einen konkreten Thread zu erzeugen, muss eine eigene Klasse aus Thread abgeleitet und die Methode run überlagert werden. Mit Hilfe eines Aufrufs der Methode start wird der Thread gestartet und die weitere Ausführung an die Methode run übertragen. start wird nach dem Starten des Threads beendet, und der Aufrufer kann parallel zum neu erzeugten Thread fortfahren. Erzeugung von Threads 14 Beispiel: Erzeugung von Threads 16 Threads können auf zwei Weisen erzeugt werden: durch Implementierung des Interfaces java.lang.runnable durch Vererbung von der Klasse Thread (die das Interface java.lang.runnable implementiert) Die Methode run() (aus dem Interface Runnable) muss implementiert werden. run() enthält die im Thread auszuführenden Anweisungen. Listing2201.java Das Beispiel zeigt einen einfachen Thread, der in einer Endlosschleife einen Zahlenwert hochzählt. Die Methode run sollte vom Programm niemals direkt aufgerufen werden. Um einen Thread zu starten, ist immer start aufzurufen.

Abbrechen eines Threads 17 Beispiel: Abbrechen mit interrupt 19 Ein Thread wird dadurch beendet, dass das Ende seiner run-methode erreicht ist. In manchen Fällen ist es jedoch erforderlich, den Thread von außen abzubrechen. Bis JDK 1.1 erfolgte dies durch die Methode stop, die aber inzwischen deprecated ist. Listing2203.java Der Thread gibt ununterbrochen Textzeilen auf dem Bildschirm aus. Das Hauptprogramm soll den Thread erzeugen und nach 2 Sekunden durch einen Aufruf von interrupt eine Unterbrechungsanforderung erzeugen. Der Thread soll dann die aktuelle Zeile fertig ausgeben und anschließend terminieren. Durch Aufruf von interrupt wird ein Flag gesetzt, das eine Unterbrechungsanforderung signalisiert. Durch Aufruf von isinterrupted kann der Thread feststellen, ob das Abbruchflag gesetzt wurde und der Thread beendet werden soll. Beispiel: Abbrechen mit stop 18 Sleep interrupted 20 Listing2202.java Gleichzeitig zum Thread fährt das Hauptprogramm mit dem Aufruf der sleep- Methode und dem Aufruf von stop fort. Beide Programmteile laufen also parallel ab. stop sollte aber nicht benutzt werden, denn es ist nicht voraussagbar und auch nicht definiert, an welcher Stelle ein Thread unterbrochen wird, wenn ein Aufruf von stop erfolgt. Besser: interrupt Erfolgt der Aufruf von interrupt während des Aufrufs von sleep, wird sleep mit einer InterruptedException abgebrochen (auch wenn die geforderte Zeitspanne noch nicht vollständig verstrichen ist). Wichtig ist hier, dass das Abbruchflag zurückgesetzt wird und der Aufruf von interrupt somit eigentlich verlorenginge, wenn er nicht direkt in der catch- Klausel behandelt würde. Wir rufen daher innerhalb der catch-klausel interrupt erneut auf, um das Flag wieder zu setzen und run die Abbruchanforderung zu signalisieren.

Weitere Methoden von Thread: sleep 21 public class ThreadJoin extends Thread { 23 public static void sleep(long millis) throws InterruptedException public static void sleep(long millis, int nanos) throws InterruptedException sorgt dafür, dass der aktuelle Thread für die (in Millisekunden und Nanosekunden angegebene) Zeit unterbrochen wird Thread.sleep kann während der Wartezeit eine Ausnahme vom Typ InterruptedException auslösen. public static void main( String args[] ) { ThreadJoin thj = new ThreadJoin(); System.out.println( "Start des Threads" ); thj.start(); try { thj.join(); catch (InterruptedException e) { System.out.println( "Main: Fertig" ); public void run() { int i = 0; while ( i < 10 ) { System.out.println( "Thread: " + i++ ); Beispiel für join Weitere Methoden von Thread: join 22 Das Interface Runnable 24 Mit der Methode public void join() throws InterruptedException public void join(long millis) throws InterruptedException kann auf das Ende des entsprechenden Threads gewartet werden (ggf. maximale Wartezeit). Nicht immer ist es möglich oder sinnvoll, eine Klasse, deren Code in einem Thread laufen soll, von Thread abzuleiten. Ausweg: Implementierung des Interfaces Runnable. Runnable enthält nur eine einzige Deklaration, nämlich die der Methode run: public abstract void run() join = vereinen

Implementieren von Runnable 25 Synchronisation 27 Um Code in einer nicht von Thread abgeleitete Klasse in dieser Weise als Thread laufen zu lassen, ist in folgenden Schritten vorzugehen: Zunächst wird ein neues Thread-Objekt erzeugt. An den Konstruktor wird das Objekt übergeben, deren run-methode parallel ausgeführt werden soll. Die Methode start des neuen Thread-Objekts wird aufgerufen. Nun startet das Thread-Objekt die run-methode des übergebenen Objekts, das sie ja durch die Übergabe im Konstruktor kennt. Wenn man sich mit Nebenläufigkeit beschäftigt, muss man sich in aller Regel auch mit Fragen der Synchronisation nebenläufiger Prozesse beschäftigen. In Java erfolgt die Kommunikation zweier Threads auf der Basis gemeinsamer Variablen, die von beiden Threads erreicht werden können. Führen beide Threads Änderungen auf den gemeinsamen Daten durch, so müssen sie synchronisiert werden, denn andernfalls können undefinierte Ergebnisse entstehen. Beispiel 26 Synchronisation 28 Listing2204.java Die Klasse B2204 ist von A2204 abgeleitet und kann daher nicht von Thread abgeleitet sein. Statt dessen implementiert sie das Interface Runnable. Um nun die run-methode der Klasse B2204 als Thread auszuführen, wird in main von Listing2204 eine Instanz dieser Klasse erzeugt und an den Konstruktor der Klasse Thread übergeben. Nach dem Aufruf von start wird die run-methode von B2204 ausgeführt. Beispiel: Listing2209.java Zwei Threads zählen einen gemeinsamen Zähler hoch. Mögliche Ausgabe: 0 1 31 33 <-- Nanu? Wo ist die 32? 34 56 32 <-- Ach so, hier!

Synchronisation 29 Monitore 31 Erläuterung Beispiel: Beide Prozesse greifen unsynchronisiert auf die gemeinsame Klassenvariable cnt zu. Da die Operation System.out.println(cnt++); unterbrechbar (also nicht atomar) ist, kommt es zu dem Fall, dass die Operation mitten in der Ausführung unterbrochen wird und der Scheduler mit dem anderen Thread fortfährt. Erst später, wenn der unterbrochene Thread wieder Rechenzeit erhält, kann er seinen vor der Unterbrechung errechneten Zählerwert von 32 ausgeben. Sein Pendant war in der Zwischenzeit allerdings bereits bis 56 fortgefahren. Um diese Art von Inkonsistenzen zu beseitigen, bedarf es der Synchronisation der beteiligten Prozesse. Durch synchronized kann entweder eine komplette Methode oder ein Block innerhalb einer Methode geschützt werden. Der Eintritt in den so deklarierten Block wird durch das Setzen einer Sperre auf einer Objektvariablen erreicht. Bezieht sich synchronized auf eine komplette Methode, wird als Sperre der this-pointer verwendet, andernfalls ist eine Objektreferenz explizit anzugeben. Wird eine statische Methode synchronisiert, erfolgt die Sperre mit Hilfe des Klassenobjekts. Monitore 30 Anwendung von synchronized auf einen Block von Anweisungen 32 Zur Synchronisation nebenläufiger Prozesse hat Java das Konzept des Monitors implementiert. Ein Monitor ist die Kapselung eines kritischen Bereichs (also eines Programmteils, der nur von jeweils einem Prozess zur Zeit durchlaufen werden darf) mit Hilfe einer automatisch verwalteten Sperre. Diese Sperre wird beim Betreten des Monitors gesetzt und beim Verlassen wieder zurückgenommen. Ist sie beim Eintritt in den Monitor bereits von einem anderen Prozess gesetzt, so muss der aktuelle Prozess warten, bis der Konkurrent die Sperre freigegeben und den Monitor verlassen hat. Beispiel: Listing2210.java: public class Listing2210 extends Thread { static int cnt = 0; public static void main(string[] args) { Thread t1 = new Listing2210(); Thread t2 = new Listing2210(); t1.start(); t2.start(); public void run() { while (true) { synchronized (getclass()) { System.out.println(cnt++); Warum sollte hier nicht this stehen?

Anwendung von synchronized auf einen Block von Anweisungen 33 Anwendung von synchronized auf eine Methode 35 Beispiel: Listing2210.java Synchronisation durch synchronized-block auf der Variablen this funktioniert leider nicht. Da der Zeiger this für jeden der beiden Threads, die ja unterschiedliche Instanzen repräsentieren, neu vergeben wird, wäre für jeden Thread der Eintritt in den Monitor grundsätzlich erlaubt. Statt dessen verwenden wir die Methode getclass, die uns ein Klassenobjekt beschafft (ein und dasselbe für alle Instanzen derselben Klasse), mit dem wir die Klassenvariable cnt schützen können. Nun werden alle Zählerwerte in aufsteigender Reihenfolge ausgegeben. Beispiel: Listing2211.java Problem: Es werden doppelte Schlüssel produziert, z.b. 10 for Thread-2 11 for Thread-4 10 for Thread-0 10 for Thread-1 11 for Thread-2 11 for Thread-3 12 for Thread-4 13 for Thread-0 Anwendung von synchronized auf eine Methode 34 Anwendung von synchronized auf eine Methode 36 Synchronisation des Zugriffs auf ein Objekt selbst, weil damit zu rechnen ist, dass mehr als ein Thread zur gleichen Zeit das Objekt verwenden will. Das Beispiel enthält ein Zählerobjekt, dessen Aufgabe es ist, einen internen Zähler zu kapseln, auf Anforderung den aktuellen Zählerstand zu liefern und den internen Zähler zu inkrementieren. Im Beispiel wird der Zähler von fünf Threads verwendet. Die Langsamkeit und damit die Wahrscheinlichkeit, dass der Scheduler die Zugriffsoperation unterbricht, wird in unserem Beispiel durch eine Sequenz eingestreuter Fließkommaoperationen erhöht. Lösung: Eine einfache Markierung der Methode nextnumber als synchronized macht diese zu einem synchronisierten Block und sorgt dafür, dass der komplette Code innerhalb der Methode wie ein synchronisierter Block behandelt wird. Ein Betreten des kritischen Abschnitts durch einen zweiten Thread ist dann nicht mehr möglich: public synchronized int nextnumber() {...

Anwendung von synchronized auf eine Methode: Erläuterung 37 wait und notify 39 Durch das synchronized-attribut wird beim Aufruf der Methode die Instanzvariable this des Counter2211- Objekts gesperrt und damit der Zutritt für andere Threads unmöglich gemacht. Erst nach Verlassen der Methode und Entsperren von this kann nextnumber wieder von anderen Threads aufgerufen werden. Diese Art des Zugriffschutzes wird in Java von vielen Klassen verwendet, um ihre Methoden thread-sicher zu machen. Nach Aussage der Sprachspezifikation kann davon ausgegangen werden, dass fast die gesamte Java- Klassenbibliothek in diesem Sinne thread-sicher (threadsave) ist. Im Einzelfall ist die Java-Dokumentation zu Rate zu ziehen. Sowohl wait als auch notify dürfen nur aufgerufen werden, wenn das Objekt bereits gesperrt ist, also nur innerhalb eines synchronized-blocks für dieses Objekt. Ein Aufruf von wait nimmt die bereits gewährte Sperre (temporär) zurück und stellt den Thread, der den Aufruf von wait verursachte, in die Warteliste des Objekts. Dadurch wird er unterbrochen und im Scheduler als wartend markiert. Ein Aufruf von notify weckt einen (beliebigen) Thread aus der Warteliste des Objekts und führt ihn dem normalen Scheduling zu. Danach versucht der Thread, den Monitor zu belegen, um seine unterbrochene Aufgabe im synchronized-block fortzusetzen. wait und notify 38 Einsatz von wait und notify: Producer/Consumer 40 Neben dem Monitorkonzept stehen mit den Methoden wait und notify der Klasse Object noch weitere Synchronisationsprimitive zur Verfügung. Zusätzlich zu der bereits erwähnten Sperre, die einem Objekt zugeordnet ist, besitzt das Objekt nämlich auch noch eine Warteliste. Dabei handelt es sich um eine (möglicherweise leere) Menge von Threads, die auf ein Ereignis warten, um fortgesetzt werden zu können. Beispiel: Listing2213.java Ein Prozess arbeitet dabei als Produzent, der Fließkommazahlen»herstellt«, und ein anderer als Konsument, der die produzierten Daten»verbraucht«. Die Kommunikation zwischen beiden erfolgt über ein gemeinsam verwendetes Vector-Objekt, das die produzierten Elemente zwischenspeichert und als Monitor für die wait-/notify-aufrufe dient. Da die Wartezeit zufällig ausgewählt wird, kann es durchaus dazu kommen, dass der Produzent eine größere Anzahl an Elementen anhäuft, die der Konsument noch nicht abgeholt hat.

Ausblick 41 Threads besitzen auch eine Reihe administrativer Eigenschaften, die besonders dann nützlich sind, wenn das Thread-Konzept stark genutzt wird. Zum einen gibt es Eigenschaften, die bei den Threads selbst zu finden sind, beispielsweise die Priorität oder der Name eines Threads. Mit Hilfe der Methode getname kann der Name eines Threads abgefragt werden: public String getname() Thread-Gruppen dienen dazu, Informationen zu verwalten, die nicht nur für einen einzelnen Thread von Bedeutung sind, sondern für eine ganze Gruppe.