0

在继续讨论基本查询之前,我首先要声明,我完全意识到我的问题违反了 AWT/Swing 框架的标准。我的查询仅作为学术经验,应该(希望)永远不会应用于现实世界的应用程序。

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

然而... 几年前,在我更熟悉 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 框架的源代码,我所有的知识都是基于互联网研究和个人经验。以上如有错误,欢迎指正。对于那些仍然对我上面的例子感到震惊的程序员,我已经更新了我的所有项目以符合标准(真是痛苦)。

4

1 回答 1

3

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

回答您的另一个问题 - 所有 GUI 组件只有一个 EDT。

“持续而明显”的变化示例:假设 JLabel 具有 HTML 内容。在您的后台线程中,设置文本并触发重绘后,PropertyChange还会触发 a,这会导致 UI 委托重新解析 HTML 并将其设置在客户端属性中(在后台线程中工作,尽管 UI 假定它是在 EDT 中,因为它正在接收事件)。

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

你可以说,“那么,我不会在我的标签中使用 HTML。” 但关键是这样的情况在 Swing 库中普遍存在——到处都有一个强烈的假设,即事件仅在 EDT 上传递,如果不阅读大量的 Swing 源代码,你不能保证你不会遇到这样的问题。

于 2013-07-31T19:52:11.803 回答