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

这是代码:

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); ,程序就可以工作new JFrame().setVisible(true); 并把try {Thread.sleep(20000);} catch(InterruptedException e) {};timer.start() 。 所以,我有点理解。 在hibernate状态下,我们保持“主”线程忙,这样定时器创建的线程就可以存在。 但是new JFrame().setVisible(true); 不要占据“主力”。 据我所知,它创建了自己的线程(如Timer)。 那么,为什么JFrame的线程可以在没有主线程和定时器线程的情况下存在呢?

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

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

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

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

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

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

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

在对Timer对象的最后一次实时引用消失并且所有未完成的任务都已完成执行之后,计时器的任务执行线程正常终止(并且变为垃圾回收)。 但是,这可能需要很长时间才能发生。 默认情况下,任务执行线程不作为守护程序线程运行,因此它能够阻止应用程序终止。 如果调用者想要快速终止计时器的任务执行线程,则调用者应该调用计时器的cancel方法。 1

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

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

因此,在计时器真正启动之前,您对计时器的最后一次引用会消失…如果您在调用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(); } }