Galileo Computing < openbook > Galileo Computing - Professionelle Bücher. Auch für Einsteiger.
Professionelle Bücher. Auch für Einsteiger

Java ist auch eine Insel von Christian Ullenboom
Programmieren für die Java 2-Plattform in der Version 5 (Tiger-Release)
Buch: Java ist auch eine Insel
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 Die Zustände eines Threads
    gp 9.3.1 Das Ende eines Threads
    gp 9.3.2 Einen Thread höflich mit Interrupt beenden
    gp 9.3.3 Der stop() von außen
    gp 9.3.4 Das ThreadDeath-Objekt
    gp 9.3.5 Auf das Ende warten mit join()
    gp 9.3.6 Threads schlafen
    gp 9.3.7 Eine Zeituhr
  gp 9.4 Arbeit niederlegen und wieder aufnehmen
  gp 9.5 Priorität
    gp 9.5.1 Threads hoher Priorität und das AWT
    gp 9.5.2 Granularität und Vorrang
  gp 9.6 Dämonen
  gp 9.7 Kooperative und nichtkooperative Threads
  gp 9.8 Synchronisation über kritische Abschnitte
    gp 9.8.1 Gemeinsam genutzte Daten
    gp 9.8.2 Probleme beim gemeinsamen Zugriff und kritische Abschnitte
    gp 9.8.3 Punkte parallel initialisieren
    gp 9.8.4 i++ sieht atomar aus, ist es aber nicht
    gp 9.8.5 Abschnitte mit synchronized schützen
    gp 9.8.6 Monitore
    gp 9.8.7 Synchronized-Methode am Beispiel der Klasse StringBuffer
    gp 9.8.8 Synchronisierte Blöcke
    gp 9.8.9 Vor- und Nachteile von synchronisierten Blöcken und Methoden
    gp 9.8.10 Nachträglich synchronisieren
    gp 9.8.11 Monitore sind reentrant, gut für die Geschwindigkeit
    gp 9.8.12 Deadlocks
    gp 9.8.13 Erkennen von Deadlocks
  gp 9.9 Synchronisation über Warten und Benachrichtigen
    gp 9.9.1 Warten mit wait() und Aufwecken mit notify()
    gp 9.9.2 Falls der Lock fehlt: IllegalMonitorStateException
    gp 9.9.3 Mehrere Wartende und notifyAll()
    gp 9.9.4 wait() mit einer Zeitspanne
    gp 9.9.5 Beispiel Erzeuger-Verbraucher-Programm
    gp 9.9.6 Semaphoren
  gp 9.10 Atomares und frische Werte mit volatile
    gp 9.10.1 Das Paket java.util.concurrent.atomic
  gp 9.11 Aktive Threads in der Umgebung
  gp 9.12 Gruppen von Threads in einer Thread-Gruppe
    gp 9.12.1 Etwas über die aktuelle Thread-Gruppe herausfinden
    gp 9.12.2 Threads in einer Thread-Gruppe anlegen
    gp 9.12.3 Methoden von Thread und ThreadGroup im Vergleich
  gp 9.13 Die Klassen Timer und TimerTask
    gp 9.13.1 Job-Scheduler Quartz
  gp 9.14 Einen Abbruch der virtuellen Maschine erkennen


Galileo Computing

9.14 Einen Abbruch der virtuellen Maschine erkennetoptop

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.20   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 © 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