我维护的 Swing 应用程序中的各种零星问题似乎是由它使用自己的自定义版本替换默认 AWT 事件队列的方式引起的Toolkit.getDefaultToolkit().getSystemEventQueue().push(new AEventQueue())
。参见例如Swing 应用程序中的线程和死锁。那里描述的问题已经解决,但是我的测试(使用 FEST Swing)现在往往会陷入僵局。
我怀疑最好的解决方案是在创建任何 Swing 组件之前,在应用程序初始化开始时替换事件队列。但是,有一些依赖关系使这很尴尬,所以目前我正试图找到一种在初始化后“推送”新事件队列的安全方法,它目前已经完成。
我尝试过的两种方法是
SwingUtilities.invokeLater()
使用;在 EDT 上推送新队列- 初始化后在主线程上推送新队列,并在使用
invokeLater()
后避免与旧 EDT 上已经启动的任何内容发生死锁。
在阅读https://stackoverflow.com/a/8965448/351885之后,我所期望的是,第一种方法可能在 Java 7 中有效,但在 Java 1.6 中可能需要第二种方法。事实上,第二个在 Java 1.6 中确实有效,而在 Java 7 中,两者似乎都成功完成,但运行非常缓慢。这可能只是一个 FEST 问题,因为应用程序本身似乎反应灵敏。
所以我几乎被迫使用第二种方法,它至少在 Java 1.6 中有效,但我想知道 - 是否有更安全的方法来实现它,因为它似乎很容易受到竞争条件的影响invokeLater
在创建新队列之后但之前出现在现有队列上的事件;- 如果有不同的方法我应该改用。
更多详情
第一个“解决方案”如下所示:
initApplication();
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
Toolkit.getDefaultToolkit().getSystemEventQueue().push(new CustomEventQueue());
}
});
当使用 Java 1.6 编译和运行时,我不明白它在做什么。似乎线程正在等待它已经持有的锁:
"AWT-EventQueue-1" prio=10 tid=0x00007f9808001000 nid=0x6628 in Object.wait() [0x00007f986aa72000]
java.lang.Thread.State: WAITING (on object monitor)
at java.lang.Object.wait(Native Method)
- waiting on <0x00000007d9961cf0> (a atlantis.gui.AEventQueue)
at java.lang.Object.wait(Object.java:502)
at java.awt.EventQueue.getNextEvent(EventQueue.java:490)
- locked <0x00000007d9961cf0> (a atlantis.gui.AEventQueue)
at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:247)
第二个“解决方案”如下所示:
initApplication();
try {
SwingUtilities.invokeAndWait(new Runnable() {
@Override
public void run() {
logger.debug("Waiting for AWT event queue to be empty.");
}
});
} catch (InterruptedException e) {
logger.error("Interrupted while waiting for event queue.", e);
} catch (InvocationTargetException e) {
logger.error("Error while waiting for event queue.",e);
}
Toolkit.getDefaultToolkit().getSystemEventQueue().push(new CustomEventQueue());
如上所述,这在 Java 1.6 中似乎可以正常工作,但我不相信它真的很安全。
我还没有弄清楚使用 Java 7 时发生了什么,但主线程似乎花了很长时间休眠方法org.fest.swing.timing.Pause.pause()
,这就是为什么我怀疑这可能是 FEST 特定的问题。