私が維持しているSwingアプリケーションのさまざまな散発的な問題は、デフォルトのAWTイベントキューをを使用して独自のカスタムバージョンに置き換える方法が原因であると思われますToolkit.getDefaultToolkit().getSystemEventQueue().push(new AEventQueue())。たとえば、Swingアプリケーションのスレッド化とデッドロックを参照してください。そこで説明されている問題は解決されましたが、私のテスト(FEST Swingを使用)はデッドロックに陥る傾向があります。
最善の解決策は、Swingコンポーネントが作成される前に、アプリケーションの初期化の開始時にイベントキューを置き換えることだと思います。ただし、それを厄介にするいくつかの依存関係があるため、当面は、初期化後に新しいイベントキューを「プッシュ」する安全な方法を見つけようとしています。
私が試した2つのアプローチは
SwingUtilities.invokeLater();を使用してEDTの新しいキューをプッシュします。- 初期化後、および使用後に新しいキューをメインスレッドにプッシュし
invokeLater()て、古いEDTですでに開始されているものとのデッドロックを回避します。
https://stackoverflow.com/a/8965448/351885を読んだ後、私が期待するのは、最初のアプローチはJava 7で機能するかもしれませんが、2番目のアプローチのようなものがJava1.6で必要になるかもしれないということです。実際、2番目はJava 1.6で機能しますが、Java 7では両方とも正常に完了するように見えますが、実行速度は非常に遅くなります。アプリケーション自体は非常に応答性が高いように見えるため、これはFESTの問題である可能性があります。
したがって、少なくともJava 1.6で機能する2番目のアプローチを使用することを余儀なくされていますが、これを実装するためのより安全な方法があるかどうかを知りたいと思います。invokeLater新しいキューが作成された後、作成される前に、既存のキューにイベントが表示されます。-別のアプローチがある場合は、代わりに使用する必要があります。
より詳しく
最初の「解決策」は次のようになります。
initApplication();
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
Toolkit.getDefaultToolkit().getSystemEventQueue().push(new CustomEventQueue());
}
});
Java 1.6を使用してコンパイルおよび実行すると、Java1.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)
2番目の「ソリューション」は次のようになります。
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固有の問題である可能性があります。