在事件调度线程上构建 Swing/AWT 小部件是否安全?

我一直在将物质外观集成到我的应用程序中,并遇到了有关其内部EDT(事件调度线程)检查例程的几个问题。实质内容绝对拒绝在 EDT 之外构造 UI 类。我做了很多Swing / AWT,我知道关于EDT的大部分规则。我使用SwingWorker,SwingUtilties.invokeLater来修改组件。我总是认为组件可以在EDT之外构建,但必须在EDT上实现操作。换句话说,您可以在后台构造和设置默认值,但对 pack/setVisible 的调用必须是 EDT 以及任何后续调用来操作组件。

我问的原因是我有一个特别“强大”的窗口来构建,涉及许多小部件,状态和资源(许多图标)。以前,我在 SwingWorker 的背景方法上构造了窗口,并使窗口在 done 方法中可见。从来没有一个问题。切换到实质后,内部EDT检查咬了我一口。

我已经能够重构代码来解决这个问题。我可以在EDT上构建,这不是一个好的解决方案,因为整个应用程序都会阻塞。我还可以重构更多,并尽力加载EDT之外的所有额外资源。

包起来...在事件调度线程上构建 Swing/AWT 小部件是否安全?


答案 1

Sun 在 2004 年更改了规则 - 在此之前,您被允许在 EDT 外部创建组件,并且只有在组件实现后才需要移动到 EDT 中。

新规则现在显示为:

为了避免死锁的可能性,必须特别注意仅从事件调度线程创建、修改和查询 Swing 组件和模型。

我的这篇博客文章提供了更多详细信息,包括指向其他相关文章的链接。请注意,所有官方的 Sun 示例都已重写,并且对此非常严格。

从历史上看,可能是多核计算机作为台式计算机的可用性不断提高,促使了规则的重新制定 - 线程问题在客户端堆栈上变得越来越明显,并且通过非常严格地遵循EDT准则,从一开始就可以防止其中的许多问题。


答案 2

不。

原因很简单,即使是EDT也喜欢在极少数情况下发生死锁,一般来说,在使用Swing时很容易使UI死锁(或者我被告知是这样)。我建议你阅读Kirill(Substance dev)博客中的这三篇文章:


推荐