Prpblem mit Thread.sleep()

Hallo, ich versuche gerade etwas zu schreiben, aber kann auch nicht genau sagen, was. Jedenfalls sollte ein JFrame nur 2 Sek. sichtbar sein:

 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package javaapplication1;

import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.SwingUtilities;
import javax.swing.WindowConstants;

/**
 * @author ikwudls
 */
public class Disappear {

    private static final int t1 = 2000;
    private long t2;
    private Runnable r = new Runnable() {
        @Override
        public void run() {
            try {
                while (true) {
                    long t3 = t2 - System.currentTimeMillis();
                    if (t3 > 0) {
                        Thread.sleep(t3);
                    } else {
                        Thread.sleep(/*bei größer 1000 funktionierts*/ t1);
                    }
                    synchronized (Disappear.class) {
                        if (System.currentTimeMillis() >= t2) {
                            d = null;
                            jf.dispose();
                        }
                    }
                }
            } catch (InterruptedException ie) {
                System.out.println(ie);
            }
        }
    };
    private JFrame jf;
    private JLabel jl;
    private static Disappear d;

    public synchronized static void show(String str) {
        if (d == null) {
            d = new Disappear();
        }
        d.show1(str);
    }

    private Disappear() {
        jf = new JFrame();
        jl = new JLabel();
        JButton jb = new JButton("Ok");
        jb.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                synchronized (Disappear.class) {
                    d = null;
                    jf.dispose();
                }
            }
        });
        jf.setLayout(new GridLayout(2, 1));
        jf.add(jl);
        jf.add(jb);
        jf.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);

        Thread t = new Thread(r);
        t.setDaemon(true);
        t.start();
    }

    private void show1(final String str) {
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                jl.setText(str);
                jf.pack();

                jf.setVisible(true);
            }
        });

        t2 = System.currentTimeMillis() + t1;
    }

    public static void main(String[] args) {
        Disappear.show("12345");
    }
}```

In Zeile 32 harkts, wenn ich als Wert z. B. nur 1000 eintrage, dann beendet die Anwendung nicht.

Wenn du Zeile 37 mit System.exit(0); austauscht, wird es auch beendet.

Das erklärt aber immer noch nicht das erscheinende Phänomen:

daemon thread wartet 1 Sek. und wird nicht beendet,
daemon thread wartet 2 oder mehr Sek. und wird beendet,

[QUOTE=Schesam]Wenn du Zeile 37 mit System.exit(0); austauscht, wird es auch beendet.[/QUOTE]Eben… Ist glaub ich einer der Gründe, warum man eine GUI in einem anderen Thread ausser “main” (mit “invokeLater()” :o das macht er ja…) startet. Ein simples “dispose()” beendet afaik den EDT nicht. Du könntest aber auch als default EXIT_ON_CLOSE verwenden.

Eine andere Möglichkeit: Synchronisiere nicht auf die gesammte Klasse (sperrt alle Klassen- und Objekt-Methoden)! Schreib irgendwo ein “Object syncobject = new Object()” und synchronisiere darauf.

Meine Vermutung dazu ist, das Dispose den aktuellen Thread beendet und wenn es der einzige momentan aktive ist (der andere schläft ja) beendet sich das Programm komplett. Bei unter 2 sek. läuft er jedoch wieder, bevor das Dispose aufgerufen wird und So läuft das Programm weiter. Mit System.exit(0) schießt man alles ab. Das ist auch der Grund warum ich von Dispose_on_Close auf Exit gewechselt bin, da das doch recht nervig ist.

Kann aber auch sein das ich totalen Stuss laber und es eig ein ganz anderer Grund ist, aber der erscheint mir plausibel.

Edit: Spacerat war schneller :stuck_out_tongue: Aber da war ich doch richtig mit meiner Vermutung, auch wenn ich daran speziell nicht gedacht hab^^

Ohne exit() wird die Anwendung erst beendet, wenn es für eine gewisse Zeit (1s) keine Events zu verarbeiten gibt (und kein displayable Zeug mehr da ist). dispose() in Zeile 37 produziert aber ständig neue Events.

Nur zur Demonstration (das hier statt Zeile 37):

if(jf.isDisplayable()) {
    jf.dispose();
}```
Kirill Grouchnikov: [AWT shutdown and daemon threads](http://www.pushing-pixels.org/2008/07/17/awt-shutdown-and-daemon-threads.html)