SwingUtilities.invokeLater()为什么需要使用?

56

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

为什么不能由 Swing 自己内部处理?为什么调用者必须关心 Swing 如何处理 UI 更新?


1
实际上,该方法正是为了让开发人员不必担心线程同步问题,你只需让Swing知道现在是更新的时候,而繁重的工作则在幕后完成。 - OscarRyz
7个回答

46

Swing对象不是线程安全的SwingUtilities.invokeLater() 允许某个任务在稍后的某个时间执行,正如其名称所示;但更重要的是,任务将在AWT事件派发线程上执行。使用 invokeLater 时,任务是异步执行的;还有一个 invokeAndWait,它不会在任务完成执行之前返回。

关于不使Swing线程安全的一些信息可以在此处找到:多线程工具包:一个失败的梦? [已存档]


2
为什么Swing不能自己内部处理?为什么调用者必须关心Swing如何处理UI更新? - pure.java
4
因为如果不在各个地方都喷洒锁定(AWT就是这么做的,结果受到了影响),很难正确实现。要求所有显示更新在分发线程中完成——在应用程序级别相当容易——可以消除大部分问题。 - Donal Fellows

17
因为 GUI 的更新必须在事件分发线程中完成。如果您在不同的线程中操作,使用 invokeLater 更新将把它从您的线程中移除并放入事件线程中。
关于此更多解释请参考:http://www.oracle.com/technetwork/java/painting-140037.html 在 Swing 中对于大型更新(例如从数据库重新填充 JTable),最明智的做法是获取底层模型,在您的线程中对模型进行更新,然后使用 invokeLater 发出通知。这样可以保持 GUI 响应事件和重绘。如果更新非常广泛,您甚至可以在更新过程中每一秒钟或两秒钟使用 invokeLater 定期发出这些通知。

10
Swing是单线程的。每次更新UI都必须来自所谓的EDT——事件分派线程,这是Swing(我认为也包括AWT)使用的主GUI线程。如果你不这样做,那么奇怪的事情可能会发生,或者一定会发生(尽管在这里我更喜欢Windows Forms,因为它只会在错误时抛出异常)。
话虽如此,你不需要将每个UI操作都包装在“SwingUtilities.invokeLater()”中——如果你编写的代码已经由EDT执行,那么这是不必要的。所以,按钮点击的ActionListener不需要这个。但是,对于在其他线程中运行的外部对象上的监听器,它会更新某个JLabel——这时就需要它了。

5
Swing并不是为了成为线程安全的GUI工具包而编写的,因此所有GUI更新都应该从单个线程中进行,以避免任何死锁。在Swing中,这是事件分派线程(EDT)。
有关更多详细信息,请参见Java教程中的Swing中的Concurrent。它还引用了this关于为什么难以编写多线程GUI工具包的博客文章。

3
所有组件的绘制都应该在单个线程中执行,这样它们才能正确渲染。这样,组件就会知道哪个部分已经被绘制,哪个部分还没有。
如果您在EDT之外调用“绘画”相关方法(paint、update、paintComponent、show、setVisible、pack等),则会尝试在两个不同的线程中进行绘画,这可能会带来问题。
当您需要使用另一个线程更新UI时,应使用invokeLater工具,它将把它放在EDT中,以便您仍然在同一个线程中进行绘画。
如果您正在EDT中运行的方法中编码(例如,actionPerformed或paint或其中之一),或者如果您正在执行与UI无关的代码(例如,在后台处理文件等),则不需要使用它。
要更好地理解所有这些概念,请阅读:单线程规则

2

SwingUtilities.invokeLater()

调用此方法将会异步地在AWT事件派发线程上执行doRun.run()方法。这将会在所有待处理的AWT事件被处理完后执行。当应用程序线程需要更新GUI时,应该使用此方法。
...


1

重复他人的话:Swing不是线程安全的,因此一个线程必须执行所有更新以避免并发问题。invokeLater是一个实用方法,用于在事件处理线程中执行某些操作。

为什么Swing不在内部执行:这是我的印象...我认为这会过度 - 检查每个更新发生的地方。它会使Swing代码膨胀,难以审查和维护代码。

另一方面,对于应用程序来说,知道它是否在GUI线程中执行并调用invokeLater并不那么困难。当应用程序在启动某个线程之前时,就会出现这种情况。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接