11.3 | Zustände von Threads |
Vor der Behandlung der einzelnen Synchronisationstechniken soll zunächst ein Überblick über die Zustände gegeben werden, in denen sich Java-Threads befinden können:
- Da Threads mit Klassen dargestellt werden, muss man zunächst mit dem new-Operator ein Exemplar erzeugen. In diesem Zustand kann man die Priorität des Threads einstellen oder das Daemon-Flag setzen. Ferner kann man den Thread auch einer Thread-Gruppe zuordnen.
- Mit dem Aufruf der Methode start() wird der Thread rechenwillig, d. h., er wartet auf die CPU, um ausgeführt zu werden.
- Der Scheduler der Virtual Machine bringt den Thread durch Zuteilung der CPU zur Ausführung. In diesem Zustand hat der Thread alle Ressourcen, die er benötigt, einschließlich der CPU. Welcher rechenwillige Thread zur Ausführung kommt, hängt von der Priorität ab. Gegebenenfalls spielt auch der plattformabhängige Scheduling-Algorithmus der Virtual Machine eine Rolle. Der Übergang vom rechenwilligen in den ausgeführten Zustand kann vom Programmierer nicht beeinflusst werden, wohl aber der umgekehrte Übergang: Mit der Methode yield() kann ein Thread die CPU freiwillig wieder abgeben.
- Mit der im Abschnitt 11.3.2 beschriebenen Technik kann ein Thread beendet werden. Im beendeten Zustand dürfen nur noch Attributwerte wie der Name des Threads abgefragt werden. Insbesondere darf ein beendeter Thread nicht mehr erneut gestartet werden. Die
Methode stop(), mit der man Threads auch vorzeitig beenden kann, wurde in Version 1.2 verworfen, da ihr Aufruf unter bestimmten Bedingungen Inkonsistenzen verursacht.
- Mit der Methode sleep() kann die Ausführung eines Threads für einen bestimmten Zeitraum ausgesetzt werden. Während dieser Zeit kann er von einem anderen Thread durch Aufruf von interrupt() unterbrochen und wieder in den rechenwilligen Zustand versetzt werden. Die vorzeitige Unterbrechung wird dem Thread durch eine InterruptedException signalisiert, damit er die Unterbrechung von der normalen Beendigung der sleep()-Methode unterscheiden und gegebenenfalls erforderliche Aktionen ausführen kann. Im schlafenden Zustand behält ein Thread alle Monitore, die er besitzt.
- In den blockierten Zustand kommt ein Thread dann, wenn er sich mit einem anderen Thread synchronisieren oder auf eine benötigte Ressource warten muss. Die Synchronisation erfolgt entweder auf das Ende eines anderen Threads (join()) oder auf ein bestimmtes Ereignis hin (wait()), dessen Eintritt mit notify() signalisiert wird. Bezüglich interrupt() gilt das zuvor Gesagte.
Bis Version 1.1 konnten Threads aus dem schlafenden, rechenwilligen oder blockierten Zustand suspendiert und mit resume() wieder in den Zustand versetzt werden, den sie vorher hatten. Seit Version 1.2 wurde diese Methoden verworfen, da sie stark Deadlock-gefährdet sind.