检查线是否需要EDT?

我有一个用Swing实现的UI。 一个组件做了一些可能需要一些时间的工作,所以我使用SwingUtilities.invokeLater 。 但是,我正在阅读一些旧代码并在ActionListener找到它:

 if (!SwingUtilities.isEventDispatchThread()) { SwingUtilities.invokeLater(new Runnable() { public void run() { // code X } }); } else { // code X } 

我认为这是有道理的,因为它将code X与EDT分开。 但是,我发现它很容易出错,因为我已经使用了几次,而且两次都忘记了else部分。

问题是:是否需要检查SwingUtilities.isEventDispatchThread() ? 或者我可以假设我不在EDT并且总是使用invokeLater

非常感谢。

即使您在EDT上,稍后调用也没有问题,但它肯定会改变事件的时间,因此您必须确保在EDT时您不依赖于此处的代码序列。 话虽这么说,一个避免忘记else的简单方法是用实用程序方法包装调用:

 public static void invokeInDispatchThreadIfNeeded(Runnable runnable) { if (EventQueue.isDispatchThread()) { runnable.run(); } else { SwingUtilities.invokeLater(runnable); } } 

这样你永远不会忘记else

此外,一般来说,在你的idom重复code x是一个非常糟糕的主意,因为你可能会发现你必须修复或改进代码,你只能在一个地方做,而在另一个地方留下一个错误。

相信您的特定用例,检查isEventDispatchThread()是不必要的。 直接调用invokeLater()不会创建新线程,因此不会出现性能损失。

代码真的应该知道它是否在EDT上(如果这是相关的)。 所以java.awt.EventQueue.isDispatchThread应该留给断言。

简单地说,如果您的代码中有一个线程(A)由EDT启动,并且在该线程(A)中您有另一个线程(B)必须修改您的GUI,在这种情况下您必须在线程上使用invokeLater(B) )。 但是,如果GUI的修改是通过第一个线程(A)进行的,则不必使用invokeLater。