如果我们不生成窗口,为什么Timer不起作用?

时间:2010-03-19 15:30:35

标签: java swing timer jframe

以下是代码:

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JFrame;
import javax.swing.Timer;

public class TimerSample {
  public static void main(String args[]) {
    new JFrame().setVisible(true);
    ActionListener actionListener = new ActionListener() {
      public void actionPerformed(ActionEvent actionEvent) {
        System.out.println("Hello World Timer");
      }
    };
    Timer timer = new Timer(500, actionListener);
    timer.start();
  }
}

它会生成一个窗口,然后在终端(命令提示符)中定期打印“Hello World Timer”。如果我对此行new JFrame().setVisible(true);发表评论,则应用程序不会向命令行打印任何内容。为什么呢?

增加:

我不确定我是否正确理解答案。据我所知,计时器启动一个新线程。并且这个新线程与“主”线程同时存在。当“主”线程完成时(当一切都完成并且没有任何事情可做)时,整个应用程序终止(与定时器创建的“新”线程一起)。对吗?

已添加2:

上述说明仍未解释所有内容。例如,如果我对new JFrame().setVisible(true);发表评论并将try {Thread.sleep(20000);} catch(InterruptedException e) {};放在timer.start()之后,该计划就会有效。所以,我有点理解。使用sleep,我们保持“main”线程忙,这样定时器创建的线程就可以存在。但是new JFrame().setVisible(true);并没有占据“主要”。据我所知,它创建了自己的线程(如Timer)。那么,为什么JFrame的线程可以在没有主线程和定时器线程的情况下存在呢?

3 个答案:

答案 0 :(得分:5)

你错过了这一点。 Timer与您创建的窗口无关,当您注释掉该窗口创建行时,它也可以工作。

但是,您未能看到的是:您的主程序在timer.start()之后退出,因此,您的程序执行被终止,并随之进入计时器。

如果最后添加Thread.sleep(20000);(包括所需的异常处理),或者需要一些时间的任何其他代码,则可以验证这一点。然后,即使没有创建任何窗口,您的计时器也能正常工作。

关键是即使没有显示任何内容,JFrame仍然处于活动状态,这反过来会使您的计时器保持活动状态。

答案 1 :(得分:1)

在窗口事件循环中调用定时器函数(其中还包括调整大小,移动,重新绘制等内容)。显然,如果窗口被隐藏,则不会执行事件循环。

这是错的,请检查弗兰克的回答。

答案 2 :(得分:1)

  

对应每个Timer对象   一个单一的后台线程   用于执行所有计时器   任务,顺序。

     

在最后一次实时参考之后   定时器对象消失了   已完成的任务已完成   执行,计时器的任务执行   线程优雅地终止(和   变得垃圾   采集)。但是,这可以采取   任意长时间发生。默认情况下,   任务执行线程不运行   作为守护程序线程,所以它是有能力的   保持申请   终止。如果来电者想要   终止计时器的任务执行   线程很快,调用者应该   调用计时器的取消方法。1

那么java.util.Timer与你可能会问的javax.swing.Timer有什么关系呢?

  

在v 1.3中,另一个Timer类是   添加到Java平台:   java.util.Timer中。它和   javax.swing.Timer提供相同的   基本功能2

因此,在您的计时器真正启动之前,您对计时器的最后一次引用就会消失...如果您在调用timer.start();时注意到主要方法已完成,除非有某些内容将使你的主线程保持活动直到计时器启动,然后你的计时器可能永远不会启动。

在第一个示例中,JFrame使主线程保持活动状态。

在第二个示例中,您睡眠时间足以让timer启动,然后计时器会使主线程保持活动状态:

public static void main(String args[]) {
        //new JFrame().setVisible(true);
        ActionListener actionListener = new ActionListener() {
            public void actionPerformed(ActionEvent actionEvent) {
                System.out.println("Hello World Timer");
            }
        };
        Timer timer = new Timer(500, actionListener);
        timer.start();
        try {
            Thread.sleep(500);//<--- the timer will still die
            Thread.sleep(100);//<--- sleep for another 100 and the timer will start printing although you can't rely on it
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }