SwingUtilities.invokeLater(runnable)和Swing Timer如何工作?

时间:2013-12-12 08:23:29

标签: java multithreading swing timer invokelater

案例研究: 我在Swing中有一个包含一些模型类和一些GUI类的程序,其中我在它们中使用了几个线程,这些线程为每个runnable运行一个具有不同休眠间隔的无限循环。两个模型线程运行非常关键的工作,如果延迟从40ms上升到60ms将不再正常工作,因此它们非常关键。

但我在GUI中有数百个组件,必须在不到一秒或更频繁的时间内更新。这些组件无法使用观察者设计模式进行更新,因为它们不能仅反映模型中的更改。他们应该计算诸如剩余时间之类的东西。

问题

  1. 我认为使用数百Runnable来效率不高 使用SwingUtilities.invokeLater(runnable)调用以更新所有内容 GUI组件。因为上下文切换会有巨大的影响 副作用。所以我要避免它。我真的应该避免吗? 创建所有可运行的动作或invokeLater()swing timer不会将它们作为一个主题运行,并且即使其中包含所有Thread.sleep(500),也有一个优化方法?
  2. 为了解决上述问题,我决定使用更新方法创建一个SwingUpdatable接口。并创建一个运行evry 500ms的SingleTonSwingUpdater并运行其中注册的类的所有更新方法。观察者的设计模式让我思考这个想法。但我担心它会成为一种反模式。而且我不确定它是否会降低程序的灵活性。
  3. 如果我使用swing计时器怎么办?肯定不能理解,如果TimerTasks都应该在500ms的时间间隔内运行,那么就不应该为它们创建一个新的线程,它足以在runnables上执行循环并执行它们相继。
  4. Java是否有针对这个问题的内置解决方案,或者是否有我可以使用的设计模式,或者我应该依赖我的解决方案,它在第一时看起来很脏?

2 个答案:

答案 0 :(得分:1)

好吧,如果你有一长串的Runnables等待执行,那么在EDT上花费的时间会增加,你的时间可能会消失。但你应该至少做一个粗略的测试,看看是否会发生这种情况。否则你将试图解决你没有的问题。

您可以尝试将事件合并在一起,以避免做不必要的工作。最后要说的是,如果你的应用程序对时间敏感,你也需要注意垃圾收集(尽管这不应该是你第一次担心)。

答案 1 :(得分:1)

  1. SwingUtilities.invokeLater(runnable)在队列中添加runnable,然后GUI线程一次执行一个,因此上下文切换最小。避免在GUI线程上运行的作业中使用Thread.sleep(),而是使用Swing计时器。

  2. 建议的“解决方案”增加了数据可视化的延迟,并且没有任何好处。小心为您不完全理解的问题添加解决方案。人的直觉在计算机内部工作很糟糕。

  3. Swing的计时器管理定时作业的队列,并在延迟到期时将它们传递给GUI线程。这是一种非常有效的方法。

  4. 你在说什么问题?每秒数百个事件并不多,标准方法应该有效。如果他们不这样做,可能会被误用。