使用EDT调度简单事件的必要性

时间:2013-07-31 19:45:07

标签: java swing awt event-dispatch-thread

在我继续讨论基本查询之前,我首先要说明我完全清楚我的问题是违反AWT / Swing框架的标准。我的查询仅仅是一种学术体验,应该(希望)永远不会应用于现实世界的应用程序。

AWT / Swing框架基于基于事件的模型构建,该模型使用单个线程来分派事件。必须在事件调度程序线程(EDT)上处理所有AWT / Swing相关事件事件,并且程序员已编程的任何自定义事件必须通过函数invokeAndWait()和invokeLater()排队。虽然这个模型确保框架永远不会遇到任何类型的线程并发问题,但它给程序员试图围绕它编写代码带来了巨大的痛苦(在stackoverflow上搜索swing问题......非常少)。

然而......几年前,在我更熟悉AWT / Swing模型和EDT之前,我曾经写过违反许多java标准的代码(这些代码会让任何合理的程序员反感恐怖)。我违反的其中一个标准是调用通过不是EDT的线程更新GUI的方法。确切地说,这是一个标准的“长”任务,它位于一个辅助线程上,该线程定期使用当前进度更新JLabel。现在回顾一下代码,我意识到尽管代码直接违反了标准,但它在100%的时间都有效。我注意到没有闪烁,没有文本损坏(因为它是一个JLabel),没有抛出随机异常并且没有异常的GUI行为。当然,我从一个很小的例子中知道,人们不能简单地确定AWT / Swing标准是过度保护还是不必要的。有了这个,我的疑问就在于:

对于简单的任务,比如更新JLabel(甚至不是以恒定速率,可能每秒一次或两次),是否真的有必要通过EDT执行它?除了被整个java编程社区所鄙视之外,还有什么可能的含义(我想要一个可靠的含义列表,而不仅仅是“它可能导致EDT陷入困境”)?

假设一个模型,其中只有一个线程更新GUI(不是EDT)并且更新很少且仅在原子操作中更新(更新字符串,原始数据等),程序可以无需运行由EDT引起的问题(我想这算作黑客攻击?)。

作为一个挑战,我想知道是否有人可以通过调度来自另一个线程的事件导致明显和不变来提示演示违反AWT / Swing模型的代码(因为我不必等待2 GUI闪烁1帧的问题几个小时?

顺便说一下,这可能是不相关的,但是为新的JFrame / Window对象生成了一个新的EDT线程,还是所有这些线程都运行在同一个线程上?我无法想象一个资源密集的多窗口系统都在一个线程上运行。

注意:我从未见过或分析过AWT / Swing框架的源代码,我的所有知识都是基于互联网研究和个人经验。如果上面有任何错误,请随时纠正我。 对于那些仍然受到上述例子影响的程序员,我已经更新了所有项目以符合标准(多么痛苦)。

1 个答案:

答案 0 :(得分:3)

此失败的示例:将JLabel设置为右对齐。然后绘图需要两个步骤 - 测量文本,以计算位置,然后绘制它。如果在绘制时更改文本(例如,由于动画循环),文本似乎偶尔会跳转。

在回答您的其他问题时 - 对于所有GUI组件,只有一个EDT。

“常量和明显”更改的示例:假设JLabel具有HTML内容。在后台线程中,在设置文本并触发重绘之后,还会触发PropertyChange,这会导致UI委托重新分析HTML并将其设置在客户端属性中(在后台线程中工作,尽管用户界面假定它在EDT中,因为它正在接收事件)。

所以现在你有一个竞争条件:如果UI在完成后台线程中的HTML视图计算之前重新绘制标签(在EDT中),它将绘制旧的HTML,并且您的标签似乎不会更新。 / p>

你可以说,“那么,我就不会在我的标签中使用HTML。”但关键是这样的情况在Swing库中普遍存在 - 只有在EDT上传递事件的地方才会有强烈的假设,并且如果没有读取大量的Swing源,你就不能保证你不会遇到这样的问题。