Galileo Computing < openbook >
Galileo Computing - Professionelle Buecher. Auch fuer Einsteiger.
Galileo Computing - Professionelle Buecher. Auch fuer Einsteiger.


Java ist auch eine Insel von Christian Ullenboom
Buch: Java ist auch eine Insel (Galileo Computing)
gp Kapitel 9 Threads und nebenläufige Programmierung
gp 9.1 Prozesse und Threads
gp 9.1.1 Wie parallele Programme die Geschwindigkeit steigern können
gp 9.2 Threads erzeugen
gp 9.2.1 Threads über die Schnittstelle Runnable implementieren
gp 9.2.2 Threads über Runnable starten
gp 9.2.3 Die Klasse Thread erweitern
gp 9.2.4 Erweitern von Thread oder Implementieren von Runnable?
gp 9.3 Threads schlafen
gp 9.3.1 Eine Zeituhr
gp 9.4 Die Klassen Timer und TimerTask
gp 9.5 Die Zustände eines Threads
gp 9.5.1 Das Ende eines Threads
gp 9.5.2 Einen Thread höflich mit Interrupt beenden
gp 9.5.3 Der stop() von außen
gp 9.5.4 Das ThreadDeath-Objekt
gp 9.5.5 Auf das Ende warten mit join()
gp 9.6 Arbeit niederlegen und wieder aufnehmen
gp 9.7 Priorität
gp 9.7.1 Threads hoher Priorität und das AWT
gp 9.7.2 Granularität und Vorrang
gp 9.8 Dämonen
gp 9.9 Kooperative und nichtkooperative Threads
gp 9.10 Synchronisation über kritische Abschnitte
gp 9.10.1 Gemeinsam genutzte Daten
gp 9.10.2 Probleme beim gemeinsamen Zugriff und kritische Abschnitte
gp 9.10.3 Punkte parallel initialisieren
gp 9.10.4 i++ sieht atomar aus, ist es aber nicht
gp 9.10.5 Abschnitte mit synchronized schützen
gp 9.10.6 Monitore
gp 9.10.7 Synchronized-Methode am Beispiel der Klasse StringBuffer
gp 9.10.8 Synchronisierte Blöcke
gp 9.10.9 Vor- und Nachteile von synchronisierten Blöcken und Methoden
gp 9.10.10 Nachträglich synchronisieren
gp 9.10.11 Monitore sind reentrant, gut für die Geschwindigkeit
gp 9.10.12 Deadlocks
gp 9.10.13 Erkennen von Deadlocks
gp 9.11 Variablen mit volatile kennzeichnen
gp 9.12 Synchronisation über Warten und Benachrichtigen
gp 9.12.1 Falls der Lock fehlt: IllegalMonitorStateException
gp 9.12.2 Warten mit wait() und Aufwecken mit notify()
gp 9.12.3 Mehrere Wartende und notifyAll()
gp 9.12.4 wait() mit einer Zeitspanne
gp 9.12.5 Beispiel Erzeuger-Verbraucher-Programm
gp 9.12.6 Semaphoren
gp 9.12.7 Die Concurrency Utilities von Doug Lea
gp 9.13 Aktive Threads in der Umgebung
gp 9.14 Gruppen von Threads in einer Thread-Gruppe
gp 9.14.1 Etwas über die aktuelle Thread-Gruppe herausfinden
gp 9.14.2 Threads in einer Thread-Gruppe anlegen
gp 9.14.3 Methoden von Thread und ThreadGroup im Vergleich
gp 9.15 Einen Abbruch der virtuellen Maschine erkennen


Galileo Computing

9.15 Einen Abbruch der virtuellen Maschine erkennentoptop

Läuft ein Java-Programm in der virtuellen Maschine, so kann der Benutzer zu jeder Zeit das Programm dadurch beenden, dass er die virtuelle Maschine beendet. Dies kann aber für das Programm sehr unsicher sein, und zwar aus den gleichen Gründen wie bei einem unvermittelten Abbruch durch die stop()-Methode der Klasse Thread.

Ein Unix-System erzeugt Signale, die das Programm informieren, dass es beendet werden soll. Dies geschieht zum Beispiel, wenn der Benutzer das Programm mit der Tastenkombination (Strg)+(C) abbricht, das System herunterfährt oder der Benutzer sich vom System abmeldet. Ein Abbruchsignal ist beispielsweise SIGINT. Jedes Programm unter Unix kann diese Signale abfangen und darauf reagieren. Auf diese Weise lassen sich auch Programme schreiben, die dieses Abbruchsignal einfach ignorieren. Ein sauberes Programm kommt der Aufforderung nach, gibt Ressourcen frei und beendet sich.

Um das Ende der virtuellen Maschine zu erkennen, ist in den Versionen bis Java 1.3 viel komplizierter nativer Quellcode entstanden, der die Signale erkennt und an das Java-Programm weiterleitet. Unter Unix lässt sich die Bibliothek JavaSignals von Kevin Hester unter http://interstice.com/~kevinh/projects/javasignals/index.html verwenden, die Signale erkennt und abblockt. Seit der JDK 1.3-Version bietet die Runtime-Klasse eine Methode an, mit der sich ein Thread bei einem Abbruchwunsch informieren lassen kann.

Mit folgender Zeile starten wir den Thread t, wenn die JVM beendet wird und das Signal abgefangen werden kann. Die Formulierung ist extra vorsichtig, da unter Windows in einer Konsole zwar ähnlich wie unter Unix bei der Eingabe von (Strg)+(C) das Ende erkannt werden kann, jedoch nicht, wenn mit dem Task-Manager der Prozess beendet wird. Unter Windows ist dies ein Aufruf von TerminateProcess. Unter Unix entspricht dem ein SIGKILL-Signal.

Thread t = ...
Runtime.getRuntime().addShutdownHook( t );

Zusätzlich zum Abbruch wird der Thread auch immer dann gestartet, wenn das Programm normal beendet wird. Das Teilwort Hook erinnert an einen Haken, der sich ins System einhängt, um Informationen abzugreifen. Der Hook ist ein initialisierter, aber noch nicht gestarteter Thread. Es können durchaus mehrere Threads unter dem Shutdown-Hook installiert sein. Wenn sich dann die JVM beendet, werden die Threads in beliebiger Reihenfolge abgearbeitet.


Beispiel Eine Endlosschleife schmort im eigenen Saft. Der eingefügte Hook reagiert auf das Ende der virtuellen Maschine. Das Programm muss auf der Konsole beendet werden, da die meisten Entwicklungsumgebungen das (Strg)+(C) nicht an die Java-Umgebung weiterleiten.

Listing 9.19 ThatsMyEnd.java

class ThatsMyEnd
{
  public static void main( String args[] )
  {
     Runtime run = Runtime.getRuntime();
     run.addShutdownHook( new Thread()
     {
      public void run()
      {
         System.out.println( "Hilfe! Man will mir an die Wäsche" );
      }
     } );
     while ( true )
       ;
  }
}

class java.lang.Runtime

gp void addShutdownHook( Thread hook )
Startet den angegebenen Thread, wenn die JVM beendet wird. Der Thread kann keinen neuen Thread unter dem Hook registrieren. Die run()-Methode des Threads sollte schnell ablaufen, um das Beenden der JVM nicht länger als nötig aufzuhalten. Es ist nicht möglich (vorgesehen), das bevorstehende Ende der JVM zu verhindern.
gp boolean removeShutdownHook( Thread hook )
Entfernt den angegebenen Hook. Rückgabewert ist true, falls der Hook registriert war und entfernt werden konnte.




Copyright (c) Galileo Press GmbH 2004
Für Ihren privaten Gebrauch dürfen Sie die Online-Version natürlich ausdrucken. Ansonsten unterliegt das <openbook> denselben Bestimmungen, wie die gebundene Ausgabe: Das Werk einschließlich aller seiner Teile ist urheberrechtlich geschützt. Alle Rechte vorbehalten einschließlich der Vervielfältigung, Übersetzung, Mikroverfilmung sowie Einspeicherung und Verarbeitung in elektronischen Systemen.


[Galileo Computing]

Galileo Press GmbH, Gartenstraße 24, 53229 Bonn, Tel.: 0228.42150.0, Fax 0228.42150.77, info@galileo-press.de