简介
Swing 应用程序中的事件分派线程(EDT)负责处理与用户交互相关的事件。为了保持界面的响应性,需要谨慎地访问和修改 GUI 组件。invokeAndWait
和 invokeLater
是 SwingUtilities
类中的两个方法,用于从非 EDT 线程与 GUI 组件进行交互。理解这两个方法之间的区别对于构建响应且稳定的 Swing 应用程序至关重要。
invokeAndWait
invokeAndWait
方法从调用线程阻塞地执行给定的 Runnable
。这意味着调用线程将等待 Runnable
完成执行,然后继续执行。invokeAndWait
的语法如下:
public static void invokeAndWait(Runnable runnable) throws InterruptedException, InvocationTargetException;
特性:
- 阻塞:
invokeAndWait
方法将阻塞调用线程,直到Runnable
完成执行。 - 同步:
invokeAndWait
保证Runnable
将在 EDT 上执行,并且在Runnable
完成执行之前,EDT 上不会执行任何其他操作。 - 异常处理:如果在
Runnable
中引发异常,则该异常将被 rethrown 为InvocationTargetException
.
优点:
- 确保 GUI 一致性:
invokeAndWait
保证 GUI 在Runnable
执行期间保持一致,因为 EDT 在此期间被阻塞。 - 获取返回值:
invokeAndWait
允许从Runnable
获取返回值,因为它在调用线程上执行。 - 同步更新:如果
Runnable
需要更新 GUI 组件,则invokeAndWait
可以确保这些更新在Runnable
完成执行之前完成。
缺点:
- 阻塞调用线程:
invokeAndWait
会阻塞调用线程,从而可能导致应用程序无响应。 - 性能影响:频繁使用
invokeAndWait
可能会影响应用程序的性能,因为它会导致调用线程被阻塞。
invokeLater
invokeLater
方法将给定的 Runnable
异步调度到 EDT。这意味着 Runnable
将在某个时间点在 EDT 上执行,但不是立即执行。invokeLater
的语法如下:
public static void invokeLater(Runnable runnable);
特性:
- 非阻塞:
invokeLater
方法不会阻塞调用线程。 - 异步:
invokeLater
调度的Runnable
将在不确定的时间点在 EDT 上执行。 - 无返回值:
invokeLater
不允许从Runnable
获取返回值,因为它是在不同的线程上执行的。
优点:
- 保持响应性:
invokeLater
不阻塞调用线程,因此应用程序可以继续对用户交互做出响应。 - 提高性能:异步调度有助于分散对 EDT 的负载,从而提高应用程序的整体性能。
缺点:
- 不保证 GUI 一致性:由于
invokeLater
是异步的,因此在Runnable
执行期间 GUI 可能会发生变化。 - 无返回值:
invokeLater
不允许从Runnable
获取返回值。 - 异常处理:如果在
Runnable
中引发异常,则无法在调用线程中捕获该异常。
比较
特性 | invokeAndWait | invokeLater |
---|---|---|
同步性 | 同步 | 异步 |
阻塞 | 是 | 否 |
GUI 一致性 | 保证 | 不保证 |
返回值 | 可获取 | 不可获取 |
性能影响 | 可能影响 | 影响较小 |
响应性 | 可能降低 | 保持 |
异常处理 | 抛出 InvocationTargetException | 无法捕获 |
何时使用
使用 invokeAndWait:
- 当需要确保 GUI 在给定的
Runnable
执行期间保持一致时。 - 当需要从
Runnable
中获取返回值时。
使用 invokeLater:
- 当需要保持应用程序的响应性时。
- 当
Runnable
不需要修改 GUI 组件或获取返回值时。
最佳实践
- 尽量使用 invokeLater:使用
invokeLater
而不是invokeAndWait
将有助于提高应用程序的性能和响应性。 - 仅在必要时使用 invokeAndWait:只有在确实需要保证 GUI 一致性或获取返回值时才使用
invokeAndWait
。 - 使用 try-catch 块处理异常:在
Runnable
中使用 try-catch 块捕获异常,并在调用线程中检查InvocationTargetException
以获取任何抛出的异常。
总结
invokeAndWait
和 invokeLater
是在 Java Swing 应用程序中与 GUI 组件进行交互的两个重要方法。理解它们的差异对于编写响应且稳定的应用程序至关重要。通过明智地选择合适的方法,可以平衡 GUI 一致性、性能和响应性之间的权衡。