Weitere aktuelle Java-Titel finden Sie bei dpunkt.
 Inhaltsverzeichnis   Auf Ebene Zurück   Seite Zurück   Seite Vor   Auf Ebene Vor   Eine Ebene höher   Index


11.8

Zeitgesteuerte Ausführung von Threads


In [1.3]Version 1.3 wurde die Standardbibliothek um zwei Klassen erweitert, die die Ausführung periodisch wiederkehrender Vorgänge (Tasks) ermöglichen. Es handelt sich hierbei um die Klassen Timer und TimerTask aus dem Paket java.util.

Timer hat dabei die Steuerfunktion und führt die einzelnen Tasks als Threads aus. TimerTask stellt einen einzelnen Task dar und implementiert das Interface Runnable, damit die einzelnen Tasks als Threads ausgeführt werden können. In der Methode run() müssen dann die Aktionen implementiert werden, die periodisch ausgeführt werden sollen.

Um einen Pozess zeitgesteuert ablaufen zu lassen, sind im Einzelnen folgende Schritte erforderlich:

Den Timer-Methoden zum Registieren von Tasks muss neben einem TimerTask-Exemplar die Periodendauer sowie der Startzeitpunkt übergeben werden. Dieser kann entweder absolut oder als relative Verzögerung gegenüber der aktuellen Systemzeit angegeben werden.

Für die Einstellung der Periodendauer zwischen zwei Ausführungen bestehen ebenfalls zwei Alternativen: Mit Ausführung ist hier eine komplette Ausführung der run()-Methode gemeint.

Das folgende Beispiel realisiert einen Thread, der von Zeit zu Zeit die Einträge in einer Warteschlange abarbeitet, die dort von einem anderen Thread abgelegt wurden. Das Beispielprogramm startet einen endlos laufenden Produzenten-Thread, der in zufälligen Zeitabständen neue Elemente in die Warteschlange einträgt. Für die Warteschlange wird die Klasse Vector verwendet. Der Produzent trägt mit dessen Methode add() neue Elemente am Ende ein, wohingegen der andere Thread mit remove() die Elemente am Anfang entfernt. Auf diese Weise wird der Vector als FIFO-Speicher benutzt.
  public void run() {
    int newValue;
    while(true) {
      newValue = counter++;
      // Neues Element in der Queue eintragen...
      queue.add(new Integer(newValue));
      System.out.println("Put element "+newValue+" into queue.");
      // ...und warten
      try {
        Thread.sleep(random.nextInt(20)*100);
      }
      catch(InterruptedException e) {
      }
    }
  }

Ein zweiter Timer-gesteuerter Thread arbeitet die Schlange ab. Die nachfolgend gezeigte Klasse QueueProcessor ist von TimerTask abgeleitet, ermittelt in der run()-Methode die Anzahl der momentan in der Warteschlange stehenden Elemente und liest diese dann aus.
  public class QueueProcessor extends TimerTask {
  
    protected Vector queue;
  
    public QueueProcessor(Vector queue) {
      this.queue = queue;
    }
  
    public void run() {
      int currentElements = queue.size();
      for(int i = 0; i < currentElements; i++) {
        String s = queue.remove(0).toString();
        System.out.println("Processed element "+s+".");
      }
    }
  
  }
In beiden Threads wird ohne weitere Synchronisationsmaßnahmen auf die Warteschlange zugegriffen, da die Klasse Vector intern synchronisiert ist.

Das Hauptprogramm initialisiert den Vector, ein Timer-Exemplar sowie ein Exemplar von QueueProcessor. Wie bereits erwähnt, wird bei letzterem zwar ein Exemplar erzeugt, dieses wird aber noch nicht als Thread gestartet.
  Vector queue;
  Timer timer;
  TimerTask processor;

  // Warteschlange, Timer und Prozessor erzeugen
  queue = new Vector();
  timer = new Timer();
  processor = new QueueProcessor(queue);

  // Produzent starten
  new Thread(new Producer(queue)).start();
  // Prozessor-Thread registrieren
  timer.scheduleAtFixedRate(processor, 5000, 10000);
Danach wird der Produzent gestartet und das QueueProcessor-Exemplar beim Timer registriert. Hierzu wird im Beispiel die Methode scheduleAtFixedRate() aufgerufen, die den Task nach einer erstmaligen Verzögerung von fünf Sekunden alle zehn Sekunden startet.

Um einen TimerTask zu deaktivieren, definiert diese Klasse die Methode cancel(). Nachdem sie einmal aufgerufen wurde, wird der Task künftig nicht mehr ausgeführt. Auch Timer verfügt über diese Methode. Hier werden alle Tasks verworfen und anschließend der Timer selbst beendet.

Material zum Beispiel


 Inhaltsverzeichnis   Auf Ebene Zurück   Seite Zurück   Seite Vor   Auf Ebene Vor   Eine Ebene höher   Index

Copyright © 2002 dpunkt.Verlag, Heidelberg. Alle Rechte vorbehalten.