SwingUtilities.invokeLater()为什么需要它?

pur*_*ava 44 java swing

为什么需要将GUI更新代码放入SwingUtilities.invokeLater()

为什么它不能被Swing本身内部照顾?为什么调用者必须关心swing如何处理UI更新?

Ric*_*arn 41

Swing对象不是线程安全的.SwingUtilities.invokeLater()允许任务在稍后的某个时间点执行,顾名思义; 但更重要的是,该任务将在AWT事件派发线程上执行.使用时invokeLater,任务以异步方式执行; 还有invokeAndWait,在任务完成执行之前不会返回.

关于决定不使Swing线程安全的一些信息可以在这里找到:多线程工具包:一个失败的梦想?

  • @pure:因为没有在整个地方喷射锁定很难做到正确(AWT这样做,并且遭受了它).要求所有显示更新都在调度线程中完成 - 在应用程序级别相当容易 - 使得大多数恶意消失. (4认同)
  • 为什么它不能由Swing本身内部照顾?为什么调用者必须关心swing如何处理UI更新? (2认同)

Pau*_*lin 16

因为GUI更新必须在事件派发线程中完成.如果你在另一个线程中运行,那么在你的线程中进行更新invokeLater并进入事件线程.

更多解释如下:http://www.oracle.com/technetwork/java/painting-140037.html

在Swing上进行大更新(比如从数据库重新填充JTable)的聪明之处是获取底层模型,在线程中对模型进行更新,然后使用激活通知invokeLater.这可以让你的gui响应事件和重绘.如果更新非常广泛,您甚至invokeLater可以在更新时定期触发这些通知,例如每隔一两秒.


Joe*_*oey 8

Swing是单线程的.UI的每次更新都必须来自所谓的EDT - 事件 - 调度线程,它是Swing(我认为AWT)使用的主要GUI线程.如果你不这样做,那么可能会或将要发生奇怪的事情(虽然我更喜欢Windows FOrms,如果你做错了就会抛出异常).

话虽这么说,你不需要将每个UI操作包装成SwingUtilities.invokeLater()- 如果你正在编写的代码已经由EDT执行,则不需要.所以ActionListener点击按钮不需要这个.但是一个外部对象的监听器,在其他一些线程中运行,在JLabel某个地方更新- 你需要它.


Mar*_*ark 5

Swing没有被编写为线程安全的GUI工具包,因此所有GUI更新都应该从单个线程发生,以避免任何死锁.在Swing中,这是事件调度程序线程(EDT).

有关更多详细信息,请参阅Java教程中的Swurrent中的Concurrent.它还引用了这篇博客文章,说明为什么编写多线程GUI工具包很困难.