SwingUtilities中的invokeAndWait方法

请在SwingUtilities中解释invokeAndWait()方法。我无法理解这一点。 解释得非常清楚。 如果你尝试一个例子,这将是非常有帮助的。

编辑添加@ noob的问题的扩展:

什么不清楚这个 ?

这是一个修改的用法示例:

import javax.swing.SwingUtilities; public class InvokeAndWaitStuff { public static void main(String[] args) { final Runnable doHelloWorld = new Runnable() { public void run() { System.out.println("Hello World on " + Thread.currentThread()); } }; Thread appThread = new Thread() { public void run() { try { SwingUtilities.invokeAndWait(doHelloWorld); } catch (Exception e) { e.printStackTrace(); } System.out.println("Finished on " + Thread.currentThread()); } }; appThread.start(); } } 

输出:

 Hello World on Thread[AWT-EventQueue-0,6,main] Finished on Thread[Thread-0,5,main] 

为什么这很重要?

导致doHelloWorld.run()在AWT事件派发线程上同步执行。 这个调用会阻塞,直到所有待处理的AWT事件都被处理,然后doHelloWorld.run()返回。 应用程序线程需要更新GUI时应使用此方法。

据我所知,这基本上是一个瓶颈,迫使GUI更新由单个线程同步执行,而不是由多个线程asynchronous执行,这可能是不安全的。

要理解invokeAndWait()作用,首先需要了解Swing的事件/线程模型。

基本上, 以任何方式影响GUI的一切都必须发生在单个线程上 。 这是因为经验表明,multithreading的GUI是不可能正确的。

在Swing中,这个特殊的GUI线程被称为Event Dispatch Thread(或者EDT) 。 一旦显示Swing顶级组件,就会启动它,并且它基本上是一个工作线程,它具有一个接一个地执行的事件对象的FIFO队列。

当需要绘制或更新Swing GUI时,JRE会在EDT队列中放置一个事件。 导致侦听器被调用的用户操作以EDT队列上的事件开始。 和(这是重要的部分)你的程序所做的改变GUI的东西(比如注册监听器,添加/删除GUI组件或改变GUI显示的模型数据)必须放在EDT队列中,或者GUI可以得到损坏。

现在完成: invokeAndWait()将您传递给它的Runnable放到EDT事件队列中,等待EDT执行完成。 当非GUI线程需要做一些影响GUI的事情时,应该使用它,但是也需要等到实际完成之后才能继续。 如果你只是想做一些影响GUI的东西,但不关心什么时候完成,你应该改用invokeLater()

我在JTable中有类似的问题。 该程序在“scrollRectToVisible”方法的某个地方被阻止。 我已经通过将其包装在invokeLater调用中来取代该调用。 invokeAndWait没有解决我的块问题。

  SwingUtilities.invokeLater(new Runnable() { @Override public void run() { table.scrollRectToVisible(r); } });