Threads
- Write code to define, instantiate and start new threads using both java.lang.Thread and java.lang.Runnable.
- Recognize conditions that might prevent a thread from executing.
- Write code using synchronized wait, notify and notifyAll to protect against concurrent access problems and to communicate between threads.
- Define the interaction among threads and object locks when executing synchronized wait, notify or notifyAll.
Write code to define, instantiate and start new threads using both java.lang.Thread and java.lang.Runnable.
Threads bedeutet, nebenläufige Prozesse, die (quasi) nebeneinander laufen. Jeder Thread ist ein einzelner sequenzieller Weg der Ausführung von Code.Sie teilen sich die gleichen Speicher, Daten und Objekte.
Es gibt zwei Möglichkeiten, um ein Thread zu erzeugen:
- Von der Threads-Klasse ableiten
Das ist der einfachste Weg, um ein Thread zu erzeugen.
Dazu wird die eigene Klasse definiert und von der Thread-Klasse vererbt.
Um den Thread zu starten, wird der die Methode start() aufgerufen, die automatisch die run()-Methode aufruft.
Beispiel: public class MeinThread extends Thread { public void run ( ){ System.out.println ( "Ausführen des Threads mittels der Thread-Klasse"); } public static void main ( String args[]) { MeinThread mt = new MeinThread(); mt.start( ); } }
- Interface Runnable implementieren
Die Schritte dazu sind:
- Interface Runnable implementieren
- run()-Methode definieren
- Eine Instanz der Klasse bilden
- Instanz der Thread-Klasse bilden und die Instanz der Klasse in den Konstruktor der Thread-Klasse übergeben
- start()-Methode der Thread-Klasse aufrufen
Beispiel: public class MeinThread implements Runnable { public void run() { System.out.println ("Ausführen der Thread mittels Implementierung"); } public static void main ( String args[]) { MeinThread mt = new MeinThread(); Thread t = new Thread (mt); t.start ( ); } }
Um einen Thread zu starten, wird immer start aufgerufen. Dadurch wird der neue Thread erzeugt und initialisiert. dadurch wird selbständig run aufgerufen, um den Anwendungscode auszuführen.
Die run()-Methode kann auch direkt aufgerufen werden. Dann ist aber diese Methode eine ganz gewöhnliche Methode und erzeugt kein Thread.
Es ist zu beachten, dass die Methode run() public ist und keinen Rückgabewert hat.
Recognize conditions that might prevent a thread from executing.
Es gibt verschiedene Methoden, um die Ausführung des Threads zu verhindern:- yield
- versetzt den Thread vom "running"-Zustand in den "ready"-Zustand
- wenn kein anderer Thread den ready-Zustand hat, kann der aktuelle Thread die Ausführung fortsetzen.
- Threads, die zeitraubende Operationen ausführen, sollten die yield()-Methode aufrufen, damit die anderen Threads auch ausgeführt werden können.
- yield()-Methode ist statisch
- sleep
- versetzt den Thread für eine gewisse Zeit in einen Schlafzustand.
- ist ebenfalls eine statische Methode, die mit einem (long millis) oder zwei Parameter (long millis, int nanos) aufgerufen wird. Der zweite Parameter erlaubt noch genaue Wartezeit
- sleep sollte innerhalb eines try-catch-Blocks aufgerufen werden, weil sleep während der Wartezeit eine Ausnahme vom Typ InterruptedException auslösen kann.
- Nach der Wartezeit geht der Thread in den ready-Zustand. Wenn andere Threads im ready-zustand befinden, so muss dieser Thread warten, bis er wieder an der Reihe ist.
- wait
ist Methode der Objektklasse und nicht der Thread-Klasse. Die Erklärung dazu ist im unteren Abschnitt
- Priorität
Threads haben Prioritäten. Der Thread kann unterbrochen werden, weil ein anderer Thread mit hoher Priorität zur Ausführung bereit ist. Es gibt drei Konstanten in der Klasse. MAX_PRIORITY(10), MIN_PRIORITY(1) und NORM_PRIORITY(5). Ein neuer Thread erhält seine Priorität vom Thread, der ihn erzugt hat (normalerweise NORM_PRIORITY). Mit getPriority() setPriority() kann man die Priorität eines Threads abfragen bzw. setzen. - blocked
Eine blockierende I/O-Methode wurde aufgerufen und der Thread ist blockiert. - time-slicing
Einem Thread wird erlaubt, nur für eine bestimmte Zeit zu laufen. Dadurch wird verhindert, dass ein Thread mit hoher Priorität die ganze CPU-Zeit für sih beansprucht.
Write code using synchronized wait, notify and notifyAll to protect against concurrent access problems and to communicate between threads.
Define the interaction among threads and object locks when executing synchronized wait, notify or notifyAll.
Beide Teile sind wieder zusammengesetztHier ist als erstes wichtig zu wissen, dass die Methoden wait(), notify() und notifyAll() nicht aus der Thread-Klasse kommen, sondern von der Objektklasse.
Diese Methoden können nur synchronized aufgerufen werden, d. h. sie können nur aufgerufen werden, wenn das Objekt gesperrt ist.
Threads laufen im gleichen Speicherbereich. Sie haben gemeinsamen Zugriff auf alle Daten und Objekte. Wenn zum Beispiel ein Thread in den gemeinsamen Objekt Daten reinschreibt und ein anderer Thread diese Daten liest, kann es Probleme auftreten, wenn der erste Thread noch nicht fertig war. Deshalb hat jedes Objekt eine Sperre und nur ein einziger Thread kann diese Sperre zur gleichen Zeit besitzen. Wenn ein Objekt mit einer synchronisierten Methode instanziiert wird, erhält diese Methode einen Monitor, sozusagen einen Überwacher. In diesem Monitor wird nur ein Thread überwacht. Alle anderen Threads müssen solange warten, bis dieser Thread die Ausführung beendet hat. Dadurch wird sichergestellt, dass nur ein Thread Zugriff auf die Daten hat. Ein Thread, der die wait()-Methode eines Objekts aufruft, hebt vorübergehend alle Sperren auf, die dieser Thread vergeben hat und dieser Thread wird dann zur Liste der wartenden Threads hinzugefügt und unterbricht seine Ausführung. Wenn ein anderer Thread jezt die notify()-Methode aufruft, dann weckt das Objekt einen der wartenden Threads auf und lässt ihn weiterarbeiten (besser gesagt versetzt den Thread in den ready-Zustand). Wie aus dem Namen zu erkennen ist, weckt die Methode notifyAll() alle wartenden Threads und versetzt sie in den ready-Zustand. Threads, die die Verarbeitung wieder weiterführen möchten, müssen die Sperre des Monitors erneut holen.
Die wait()-Methode sollte in einem try-catch-Block geschrieben werden, weil hier InterruptedException auftreten kann.