2013-12-12 42 views
1

学习案例: 我有一个程序,其中包含一些模型类和Swing中的一些GUI类,其中我使用了两个线程中的多个线程,每个线程为每个可运行的线程运行不同的睡眠间隔。两个模型线程运行非常关键的工作,其中如果延迟从40ms上升到60ms将不再正确工作,所以它们非常关键。SwingUtilities.invokeLater(runnable)和Swing Timer如何工作?

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

问题

  1. 我认为它不会是有效地使用数百Runnable小号 与SwingUtilities.invokeLater(runnable)调用来更新所有 GUI组件。因为上下文切换会产生巨大的副作用。所以我要避免它。我真的应该避免 创建所有这些可运行或invokeLater()swing timer并不运行它们作为一个线程,具有即使所有的Thread.sleep(500)它们之间的优化方法?
  2. 为了解决上述问题,我决定与更新方法创建一个接口SwingUpdatable。并创建一个运行evry 500ms的SingleTonSwingUpdater,并运行注册它的类的所有更新方法。观察者的设计模式让我思考这个想法。但我担心这将是一种反模式。我不确定它是否会降低程序的灵活性。
  3. 如果我使用什么样的挥杆定时器。它肯定不能理解,如果TimerTasks都应该在500毫秒的时间间隔内运行,所以不应该有一个新的线程,它足以在runnables上做一个循环并且一个接一个地执行它们。
  4. 确实的Java有此问题的内置解决方案或者是我可以使用设计模式或者我应该依赖于我的解决方案,在第一看起来这么脏?
+0

那么NASA的任务控制应用程序是用'Swing'写成的?很高兴知道。 – vikingsteve

回答

1
  1. SwingUtilities.invokeLater(可运行)在队列中增加了可运行,然后GUI线程执行它们一次一个,所以上下文切换是最小的。避免在GUI线程上运行的作业中使用Thread.sleep(),而应使用Swing计时器。

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

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

  4. 你说什么问题?每秒数百个事件并非如此,标准方法应该可行。如果他们不这样做,他们可能被滥用。

+0

我并没有完全执行这部分程序,但我的直觉表明它可能会在某一天失败。因为它是用于单核处理器的工业用途。有一些解决方案可以读取他们的位置并且停止他们是非常关键的,如果我不能读取位置并且他们通过停止间隔,他们将行进到行的末尾。而该程序有数百个摆动复合组件,它们应该计算一些关于不同对象状态的信息并更新它们自己。 – Johnny

+0

顺便说一句,我现在明白了,我认为只有当我在我的通用单人挥杆更新程序中使用摆动计时器时,才可以使用我的解决方案。尽管如此,我还是不确定拥有数百个定时器是否是一个安全的解决方案,尤其重要的是要考虑每小时使用这些定时器创建数千个对象,其余部分必须进行垃圾收集 – Johnny

+0

Swing本身每秒可以生成数百个事件对象(当一个鼠标指针移动时),每小时几千个对象的数量可以忽略不计。无论如何,创建,绘图和回收对象需要无限期的时间,所以java + Swing不应该用于实时应用程序。只需制作一个原型,并确保至少有10倍的处理器时间。优化您的应用程序以使用更少的内存和CPU时间,但只能在测量之后使用。优化不是瓶颈的东西没有效果。 –

1

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

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