Java:Swing Libraries & Thread Safety
我经常听到对 Swing 库中缺乏线程安全性的批评。然而,我不确定在我自己的代码中会做什么可能会导致问题:
在什么情况下,Swing不是线程安全的事实会发挥作用?
我应该积极避免做什么?
我经常听到对 Swing 库中缺乏线程安全性的批评。然而,我不确定在我自己的代码中会做什么可能会导致问题:
在什么情况下,Swing不是线程安全的事实会发挥作用?
我应该积极避免做什么?
切勿执行长时间运行的任务来响应按钮、事件等,因为这些任务位于事件线程上。如果阻止事件线程,整个 GUI 将完全没有响应,从而导致用户非常生气。这就是为什么Swing看起来很慢和粗糙。
使用 Threads、Executors 和 SwingWorker 在 EDT(事件调度线程)上运行任务。
请勿在 EDT 外部更新或创建小部件。在EDT之外,你唯一能做的调用就是Computral.repaint()。使用 SwingUtilitis.invokeLater 确保某些代码在 EDT 上执行。
如果你遵循这些规则,Swing可以做出一些非常有吸引力和响应迅速的GUI。
一些非常棒的Swing UI工作的例子:Palantir Technologies。注意:我不为他们工作,只是一个很棒的挥杆的例子。可惜没有公开演示...他们的博客也很好,稀疏,但很好
这是让我很高兴我买了Robinson & Vorobiev关于Swing的书的问题之一。
任何访问 java.awt.Component
状态的内容都应该在 EDT 内部运行,但有三个例外:任何专门记录为线程安全的内容,例如 、 、 和 ;UI 中尚未实现的任何组件;以及该小程序之前小程序中的任何组件都已被调用。repaint()
revalidate()
invalidate()
start()
特制的线程安全方法非常罕见,通常只需记住那些就足够了。您通常也可以假设没有这样的方法(例如,在SwingWorker中包装重绘调用是完全安全的)。
“已实现”表示组件是顶级容器(如 JFrame),其中任何 、 或 已调用,或者已将其添加到已实现的组件中。这意味着在main()方法中构建UI是完全可以的,就像许多教程示例一样,因为它们不会调用顶级容器,直到每个组件都已添加到其中,字体和边框配置等。setVisible(true)
show()
pack()
setVisible(true)
出于类似的原因,在其方法中构建小程序 UI,然后在构建完所有 API 后进行调用是完全安全的。init()
start()
将后续组件更改包装在 Runnables 中以发送到,只需执行几次即可轻松正确。我觉得烦人的一件事是从另一个线程读取组件(例如)的状态。从技术上讲,这也必须包含在 中;在实践中,它会使代码变得丑陋,而且我经常不打扰,或者我会小心翼翼地在初始事件处理时间(通常是在大多数情况下这样做的正确时间)获取该信息。invokeLater()
someTextField.getText()
invokeLater()