Wie kann man ein Java-Programm eine bestimmte Aufgabe rhythmisch wiederholt ausführen lassen?
Das Beispiel zeigt zwei Klassen, von denen Zeitsteuerung
die main()
-Methode enthält und eine einfache
GUI mit zwei JButton
und einem JLabel
bereitstellt. Die Buttons starten und stoppen eine einfache
Routine, die im Abstand von 1,5 sec (1500ms) ein '+' auf ein JLabel
setzt. Die zweite Klasse Task
ist von TimerTask
abgeleitet und erbt eine Methode run()
, in der der
Vorgang ausgeführt wird.
Aufgrund ihrer Einfachheit ist neben dem Aufbau des GUI fast die
gesamte Programmsteuerung innerhalb zweier anonymer Klassen in
der Methode initGUI()
lokalisiert. Sie wird
ihrerseits im Konstruktor der GUI-Klasse aufgerufen. Die
anonymen Klassen stellen die ActionListener
dar,
die die Zeitsteuerung starten und stoppen.
Die Startfunktion
greift auf die Instanzvariable des Typs Timer
zu,
initialisiert diesen neu und führt auf ihm dessen Methode schedule()
aus. Ihr werden drei Parameter übergeben:
Typ | Funktion |
---|---|
Task | Referenz der von TimerTask abgeleiteten Klasse |
long | Startzeitpunkt gemessen vom Beginn der Ausführung an |
long | Zeitlicher Abstand rhythmisch addiert vom Startzeitpunkt an. Wird hier ein Wert von 1500 angegeben, so bedeutet dies, dass die zweite Ausführung nach 3000ms, die vierte nach 4500ms, etc. stattfindet.1) |
Das Timer
-Objekt muss vorher neu gebildet worden
sein, da es im ActionListener
des Stop-Buttons
durch cancel()
beendet wird und anschließend
nicht erneut gestartet werden kann.
Dem Task
-Objekt wird in jedem Falle eine Referenz
auf die Klasse Zeitsteuerung
übergeben, um
einen Zugriff auf dessen Getter- und Setter-Methoden zu
ermöglichen, die wiederum die Manipulation des Label-Textes
ermöglichen. Dies geschieht so, dass in Task
die Referenz an eine Instanzvariable übergeben wird,
über die die Methodenaufrufe in run()
erfolgen.
import java.awt.BorderLayout;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Timer;
import java.util.TimerTask;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class Zeitsteuerung {
private Timer t;
private JLabel label;
public Zeitsteuerung() {
initGUI();
}
private void initGUI() {
JFrame frame = new JFrame("Zeitsteuerung");
label = new JLabel(" ");
JButton butt1 = new JButton("Start");
butt1.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
t = new Timer();
t.scheduleAtFixedRate(new Task(Zeitsteuerung.this), 0, 1500);
t.schedule(new Task(Zeitsteuerung.this), 0, 1500);
}
});
JButton butt2 = new JButton("Stop");
butt2.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
t.cancel();
}
});
frame.add(label, BorderLayout.NORTH);
JPanel panel = new JPanel(new FlowLayout());
panel.add(butt1);
panel.add(butt2);
frame.add(panel, BorderLayout.SOUTH);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public void setText(String s) {
label.setText(s);
}
public String getText() {
return label.getText();
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> new Zeitsteuerung());
}
}
class Task extends TimerTask {
Zeitsteuerung z;
public Task(Zeitsteuerung z) {
this.z = z;
}
public void run() {
z.setText(z.getText() + "+");
}
}
1) Die Methode schedule()
ist mehrfach
überladen und behandelt den dritten Parameter so, dass bei
zeitlicher Verzögerung eines Ausführungsdurchgangs, der
Timer versucht 'aufzuholen', die nachfolgenden Ausführungen
also in kürzeren Zeitabständen stattfinden können.
Will man die zeitlichen Abstände konstant halten, so muss die
Methode scheduleAtFixedRate()
mit den gleichen
Parametern verwendet werden.
Wenn Ihnen javabeginners.de gefällt, freue ich mich über eine Spende an diese gemeinnützigen Organisationen.