SwingUtilities中的invokeAndWait方法

时间:2011-03-31 12:35:02

标签: java swing

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

编辑添加@ noob扩展问题:

this有什么不清楚的地方?

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

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更新由单个线程同步执行,而不是由多个线程异步执行,这可能是不安全的。

2 个答案:

答案 0 :(得分:52)

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

基本上,以任何方式影响GUI的所有内容都必须在单个线程上发生。这是因为经验表明多线程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()

答案 1 :(得分:1)

我在JTable中遇到了类似的问题。该程序在“scrollRectToVisible”方法中被阻止。我已经通过将其包装在invokeLater调用中来替换了该调用。 invokeAndWait没有解决我的阻塞问题。

    SwingUtilities.invokeLater(new Runnable() {

        @Override
        public void run() {
            table.scrollRectToVisible(r);
        }

    });