Swing Timer Tick不稳定,不规律

时间:2012-11-18 03:55:09

标签: java swing timer delay

我是Java的新手,但不是一般的编程。我在Windows Vista上使用Java 1.7.0_07。我试图弄清楚如何定期进行Swing Timer滴答。

我注意到即使我设置了计时器延迟,并且我的actionPerformed事件处理程序中没有任何内容,只有repaint()方法,但计时器滴答不稳定甚至不准确。

我一直在寻找解决方案已经有一段时间了,看了看,John B Matthews博士相当整洁Kinetic Model example。在他的例子中,默认延迟是40mS,但计时器实际上是47mS +/- 1mS(偶尔从32mS到63mS的变化)。在actionPerformed事件处理程序中花费的时间始终为0mS。这些结果源于将其代码作为应用程序运行。

如果你仔细观察'原子'的移动,那么口吃是显而易见的。我不明白是什么导致计时器以这种方式表现。 我的计算机上运行的最小Windows任务,但问题仍然存在。

是否有解决此问题的方法,还是只是Java的一个功能?

1 个答案:

答案 0 :(得分:2)

我没有查看源代码或进行了彻底的调查。但我最好的猜测是,这是“一个特色”。

javax.swing.Timer保证您在EDT上调用actionPerformed方法。因此,每当Timer达到其间隔时,它可能会在EDT上安排Runnable,而后者将调用actionPerformed方法。但是,如果EDT在那个确切的时刻忙碌(例如进行重新绘制),则无法执行Runnable

所以小延迟是不可避免的......

刚检查了源代码,似乎我的初步猜测是正确的

void post() {
     if (notify.compareAndSet(false, true) || !coalesce) {
         AccessController.doPrivileged(new PrivilegedAction<Void>() {
             public Void run() {
                 SwingUtilities.invokeLater(doPostEvent);
                 return null;
            }
        }, getAccessControlContext());
    }
}

它使用invokeLater来安排Runnable(最有可能使您不会像invokeAndWait那样累积延迟)。但这意味着在计时器发布事件和实际触发actionPerformed方法之间,EDT必须完成之前的任务。而且由于没有机制可以说:“嘿,EDT,现在就停止你正在做的事情,先完成我的工作”,没有机制可以避免延误。

也许您可以通过编写自己的Timer使用SecondaryLoop(在JDK7中提供)来获得更好的结果。但这是一个疯狂的猜测(我什么都没试过)