【发布时间】:2014-04-04 10:15:34
【问题描述】:
谁能用简单的话解释一下这段代码:
SwingUtilities.invokeLater(
new Runnable(){
public void run(){
chatWindow.append(text);
}
});
}
拜托,谁能给我详细的解释。
【问题讨论】:
谁能用简单的话解释一下这段代码:
SwingUtilities.invokeLater(
new Runnable(){
public void run(){
chatWindow.append(text);
}
});
}
拜托,谁能给我详细的解释。
【问题讨论】:
您正在创建Runnable 接口的匿名实现的实例,并将其传递给invokeLater,后者会将其放入队列中。另一个线程,Event Dispatch Thread,将 Runnables 从该队列中弹出并调用它们的run 方法。 (请注意,这确实是一个简单化的解释,并不100%符合现实。
就你作为程序员感兴趣的效果而言,这使得下面的代码行:
chatWindow.append(text);
不是在当前线程上执行,而是在事件调度线程 (EDT) 上执行。如果您尝试在当前线程上执行它,则会导致未定义的行为,因为 Swing 不是线程安全的,并且所有 GUI 操作都必须在提到的 EDT 上发生。
【讨论】:
这只是将一个任务添加到 Java 线程的任务队列中,该线程负责整个应用程序的呈现和事件。
注意:这个线程叫做EDT(事件调度线程)。
【讨论】:
这是一种将一定数量的指令传递给 AWT 事件调度线程 (EDT) 的方法。这是必需的,因为从其他线程对与 AWT 相关的事物(如 JFrame 及其所有子项)进行操作是不好的做法。你最好把它交给 EDT,让它在适当的时候处理它。
代码本身使用实现 Runnable 的匿名类,以便让您指定要在 EDT 上执行的内容。 Runnable 接口要求您实现run() 方法。然后 EDT 会在需要时调用您的类对象 run()。
【讨论】:
基本上,它会在所有 AWT 事件被消耗后立即启动内联 Runnable 对象的 run() 方法中的代码。
【讨论】:
Runnable 是 Java 中的一个接口,表示定义运行方法的类型。实现 Runnable 接口的类必须为其提供实现。 Thread 是众所周知的 Runnable。
来自docs:
导致 doRun.run() 在 AWT 事件上异步执行 调度线程。这将在所有待处理的 AWT 事件完成后发生 被处理。应用程序线程时应该使用此方法 需要更新 GUI。在以下示例中,invokeLater 调用 在事件分派时将 Runnable 对象 doHelloWorld 排队 线程,然后打印一条消息。
如果从事件调度线程调用 invokeLater -- for 例如,来自 JButton 的 ActionListener -- doRun.run() 仍将 被推迟到所有待处理的事件都处理完。
【讨论】:
虽然这些链接上很少有好的答案和解释,但我仍然在添加一些细节:
Should we use EventQueue.invokeLater for any GUI update in a Java desktop application?
http://www.javamex.com/tutorials/threads/invokelater.shtml
Swing 事件处理代码在称为事件调度线程 (EDT) 的特殊线程上运行。大多数调用 Swing 方法的代码也在这个线程上运行。这是必要的,因为大多数 Swing 对象方法都不是线程安全的。所有与 GUI 相关的任务,应该对 GUI 进行任何更新,而绘制过程必须在 EDT 上进行,这涉及将请求包装在一个事件中并将其处理到 EventQueue 中。然后事件从同一个队列中一个一个地分派,按照它们排队的顺序,先入先出。也就是说,如果事件 A 在事件 B 之前入队到 EventQueue,那么事件 B 将不会在事件 A 之前分派。
SwingUtilities 类有两个有用的函数来帮助完成 GUI 渲染任务:
1) invokeLater(Runnable):导致 doRun.run() 在 AWT 事件调度线程 (EDT) 上异步执行。这将在处理完所有未决 AWT 事件后发生,如上所述。
2) invokeAndWait(Runnable):它与invokeLater具有相同的功能,但它与invokeLater的不同之处在于: --> invokeAndWait 等待它给 EDT 的任务完成,然后返回。 --> 它阻塞(等待)当前(即,它通过同步锁发送到等待状态来调用线程继续执行。 --> 一旦这个函数发布的事件请求在EDT中被调度并且这个函数的调用者线程可以继续,它将释放锁。
【讨论】: