...
private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {
int minutes = Integer.valueOf(this.minutesTxt.getText()).intValue();
MyTimer myt = new MyTimer(minutes, this.hourLabel, this.minLabel, this.secLabel);
myt.start();
try {
myt.join(); // warten bis thread 'myt' beendet ist .. (funktioniert nicht )
} catch (InterruptedException ex) { }
... // weitere abarbeitung....
}
...
in meinem programm soll, wenn man auf einen Button klickt ein Timer herunterzählen.
Den Timer hab ich mit einer eigenen klasse MyTimer implementiert und starte ihn als eigenen Thread.
Wenn der Timer fertig ist ( Thread zu ende ) soll weiter in der abarbeitung weiter gemacht werden...
ich starte meinen timer also mit myt.start(); Das funktioniert soweit.
Hab gelesen dass ich mit join() warten kann bist dieser thread beendigt ist. erst dann wird im programmablauf weitergemacht....
So wie die methode oben steht funktionierts aber nicht... sobald ich die zeile myt.join() hinzufüge tut sich nix mehr
kann mir jemand sagen was ich falsch mache?
Wenn du innerhalb eines Listeners langwierige Berechnungen ausführst oder durch einen join-Aufruf blockierst, dann blockiert das auch den AWT-Thread, welcher die GUI Events verarbeitet.
Du könntest einen Extra-Thread aufmachen, der den Timer startet, auf dessen Beendigung wartet und dann irgendwas tut.
Oder lässt das mit dem Timer sein und baust dir stattdessen einfach einen Thread, der in einer Schleife herunterzählt und zwischendurch immer per Thread.sleep(1000) eine Sekunde wartet. Dann kannst du direkt im Anschluss an die Schleife das anhängen, was nach Beendigung ausgeführt werden soll.
das programm scheint komplett blockiert zu sein.. man kann nix mehr anklicken.
der Timer Thread ist nach einer minute fertig. (er zählt eine minute runter und zeigt sekunden an) erst nach dieser minute soll weiter gemacht werden. wenn ich join() weglösch funktioniert alles nur is es halt wichtig dass erst nach beendigung des timerthreads nächste anweisungen abgearbeitet werden....
edit: den timer hab ich übrigens mit sleep(1000) in der run()-methode der Klasse MyTimer implementiert
edit: d.h.: wenn ich join() in diese methode ausführe wird mich das sowieso nicht zum ziel führen weil änderung in der GUI nicht sichtbar sind da join() alles blockiert?
wie moormaster geschrieben hat, brauchst du entweder einen zweiten Thread, der auf den ersten wartet,
oder nur einen Thread, der am Ende selber die noch offenen Befehle ausführt
Hauptsache, die actionPerformed-Methode wird möglichst schnell beendet, dann gehts weiter
Join blockiert nicht generell alles, sondern es wartet darauf, dass der jeweilige Thread abgearbeitet wurde. Wenn du join innerhalb eines Listeners aufrufst, dann heisst das, dass der AWT Thread (welcher die Methode des Listeners aufgerufen hat) jetzt darauf warten muss, dass der Listener fertig wird, bevor er weitere Events verarbeiten kann.
Mit einem join Aufruf innerhalb des AWT Threads blockierst du den AWT Thread und somit reagiert die GUI für diese Zeit dementsprechend nicht mehr.
Hier mal ein kleines Beispiel zur Veranschaulichung Einmal mit join innerhalb des AWT Threads (->Blockierung) und einmal so, dass der Thread selbstständig herunterzählt und auch die abschliessende Aktion selbst durchführt. Es muss also niemand von aussen warten, bis der Thread fertig ist.
Code:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class Main
{
JFrame fr;
JLabel lb;
JButton bu;
JButton buBlock;
public Main()
{
// quick GUI initialization
this.fr = new JFrame();
fr.setLayout(new FlowLayout());
fr.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
this.lb = new JLabel("[ ]");
fr.add(lb);
this.bu = new JButton("start");
fr.add(bu);
this.buBlock = new JButton("start blocking");
fr.add(buBlock);
// events
bu.addActionListener(
new ActionListener()
{
@Override
public void actionPerformed(ActionEvent e)
{
// just start the Thread and leave it running -> AWT Thread will not be blocked
new Countdown(Main.this).start();
}
}
);
buBlock.addActionListener(
new ActionListener()
{
@Override
public void actionPerformed(ActionEvent e)
{
// start the thread
BlockingCountdown bc = new BlockingCountdown(Main.this);
bc.start();
// wait for it to finish
try { bc.join(); } catch (InterruptedException ex) { ex.printStackTrace(); }
JOptionPane.showMessageDialog(fr, "Countdown finished...");
// countdown has endet; actionPerformed can return -> AWT Thread can go on only AFTER finishing the countdown
}
}
);
fr.setSize(300, 100);
fr.validate();
fr.setVisible(true);
}
public static void main(String[] args)
{
new Main();
}
}
class Countdown extends Thread
{
Main ref;
public Countdown(Main ref)
{
this.ref = ref;
}
@Override
public void run()
{
// countdown
for (int i=0;i<10;i++)
{
ref.lb.setText("[" + (10-i) + "]");
try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); }
}
// final action
JOptionPane.showMessageDialog(ref.fr, "Countdown finished...");
}
}
class BlockingCountdown extends Thread
{
Main ref;
public BlockingCountdown(Main ref)
{
this.ref = ref;
}
@Override
public void run()
{
// countdown only
for (int i=0;i<10;i++)
{
ref.lb.setText("[" + (10-i) + "]");
try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); }
}
}
}
danke für die schnellen und hilfreichen antworten. Nachdem das Problem klar wurde bin ich auf folgende Thematik gestoßen http://en.wikipedia.org/wiki/SwingWorker .