SwingUtilities.invokeLater是做什么的?

54

SwingUtilities.invokeLater 是什么?它只是延迟执行其 run 方法内的一段代码吗?在 invokeLater 函数中调用操作和仅在要执行的线程末尾调用操作有何区别?请问有谁能帮助我理解 invokeLater 函数的真实作用是什么?


2
请参见以下链接以了解背景信息(相关但非重复):https://dev59.com/lVbTa4cB1Zd3GeqP_oxr - Donal Fellows
5个回答

40

正如其他答案所说,它在AWT事件分派线程上执行您的Runnable。但为什么要这样做?因为Swing数据结构不是线程安全的,为了为程序员提供一个易于实现的方法来防止并发访问它们,Swing设计者制定了规则,即所有访问它们的代码必须在同一线程上运行。对于事件处理和显示维护代码,这是自动进行的,但如果您启动了一个长时间运行的操作-当然是在新线程上-如何信号其进度或完成?您必须修改Swing控件,并且必须从事件分派线程中执行此操作。因此使用invokeLater


哦!原来这就是在Java中如何进行异步单线程操作的方法!不过奇怪的是,它必须与“窗口化”工具包捆绑在一起,似乎有点不合适。 - Dmytro
4
@Dmitry 这是一个有趣的看法。Java并没有提供单线程的语言级支持(是否有任何语言都没有呢?)。因此,需要它的框架必须提供支持它的功能,并为客户程序员制定正确使用它的规则。这不是“Java的做法”,而是在Java中完成任务的一种方式。 - Maurice Naftalin

11

这将在AWT线程上运行代码,允许你从其他线程修改GUI。

来自文档

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


3
如前所述,InvokeLater允许您在未在EventQueue上运行时安全地调用swing类中的方法。但是,您可以通过仅从EventQueue访问其他字段和类来简化代码和生活。它们可以在不涉及多线程麻烦的情况下与swing和彼此一起工作。如果您已经启动了另一个线程,请尽快使用InvokeLater返回到EventQueue,并最小化必须同步或以其他方式受保护的字段数。
如果您需要充分利用多个核心,则必须减少对EventQueue的使用,并且您将为此付出复杂性方面的巨大代价。

2

这个应该是评论,但是看起来越来越长了,只是基础的东西。

1/ 创建自己的EDT以确保正确更新GUI。例如,如果您使用普通的Threadjava.util.TimerExecutor等执行一些代码,则需要使用自己的EDT。更多信息请查看此处

2/ 帮助设置焦点JComponents,如果有一些监听器,因为如果有例如DocumentListener,那么很难将Focus设置为所需的JComponents

3/ 延迟代码执行块并将其移动到EDT的末尾。


1
请注意,每次调用invokeLater(doRun)方法时,最终都会调用您的doRun.run()方法。因此,如果在事件线程有机会执行其处理之前您调用了十次它,那么您很可能会连续收到十个对doRun.run()方法的调用。

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