3

私が維持している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固有の問題である可能性があります。

4

1 に答える 1

3

現在の EDT を新しい EDT にリセットする理由が見当たらないので、私の質問は

1) いくつかありますか

  • Java のロック解除、メモリ不足 ...

  • RepaintManager 例外、

2) 基本的にできます

  • 現在のEDTをロックThread.sleep(int)してsetVisible(false)、原因JComponentで、

  • EDT がある場合は、使用する必要があります。アクティブでない場合は、次のinvokeLater中から選択できますinvokeLaterinvokeAndWait

コード

if (EventQueue.isDispatchThread()) {
    SwingUtilities.invokeLater(new Runnable() {

        @Override
        public void run() {
            //some stuff
        }
    });
} else {
    try {
        SwingUtilities.invokeAndWait(new Runnable() {

            @Override
            public void run() {
                //some stuff
            }
        });
    } catch (InterruptedException ex) {
        Logger.getLogger(IsThereEDT.class.getName()).log(Level.SEVERE, null, ex);
    } catch (InvocationTargetException ex) {
        Logger.getLogger(IsThereEDT.class.getName()).log(Level.SEVERE, null, ex);
    }
}

3) 通知invokeAndWaitは EDT から呼び出す必要があります。そうしないとEDT exceptions、現在の EDT のロックが解除されます。

4) アクティブな EDT がない場合、その理由はありませんpush()EventQueue

5)上記のすべての簡単なテストコード..

import java.awt.EventQueue;
import java.lang.reflect.InvocationTargetException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.concurrent.*;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.*;

public class IsThereEDT {

    private ScheduledExecutorService scheduler;
    private AccurateScheduledRunnable periodic;
    private ScheduledFuture<?> periodicMonitor;
    private int taskPeriod = 30;
    private SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss");
    private Date dateRun;
    private JFrame frame1 = new JFrame("Frame 1");

    public IsThereEDT() {
        scheduler = Executors.newSingleThreadScheduledExecutor();
        periodic = new AccurateScheduledRunnable() {

            private final int ALLOWED_TARDINESS = 200;
            private int countRun = 0;
            private int countCalled = 0;
            private int maxCalled = 10;

            @Override
            public void run() {
                countCalled++;
                if (countCalled < maxCalled) {
                    if (countCalled % 3 == 0) {
                        /*if (EventQueue.isDispatchThread()) {
                            SwingUtilities.invokeLater(new Runnable() {

                                @Override
                                public void run() {
                                    //some stuff
                                }
                            });
                        } else {
                            try {
                                SwingUtilities.invokeAndWait(new Runnable() {

                                    @Override
                                    public void run() {
                                        //some stuff
                                    }
                                });
                            } catch (InterruptedException ex) {
                                Logger.getLogger(IsThereEDT.class.getName()).log(Level.SEVERE, null, ex);
                            } catch (InvocationTargetException ex) {
                                Logger.getLogger(IsThereEDT.class.getName()).log(Level.SEVERE, null, ex);
                            }
                        }*/
                        SwingUtilities.invokeLater(new Runnable() {

                            @Override
                            public void run() {
                                System.out.println("Push a new event to EDT");
                                frame1.repaint();
                                isThereReallyEDT();
                            }
                        });
                    } else {
                        if (this.getExecutionTime() < ALLOWED_TARDINESS) {
                            countRun++;
                            isThereReallyEDT(); // non on EDT
                        }
                    }
                } else {
                    System.out.println("Terminating this madness");
                    System.exit(0);
                }
            }
        };
        periodicMonitor = scheduler.scheduleAtFixedRate(periodic, 0, taskPeriod, TimeUnit.SECONDS);
        periodic.setThreadMonitor(periodicMonitor);
        SwingUtilities.invokeLater(new Runnable() {

            @Override
            public void run() {
                isThereReallyEDT();
                frame1.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame1.getContentPane().add(new JLabel("Hello in frame 1"));
                frame1.pack();
                frame1.setLocation(100, 100);
                frame1.setVisible(true);
            }
        });
        try {
            Thread.sleep(500);
        } catch (InterruptedException ex) {
            Logger.getLogger(IsThereEDT.class.getName()).log(Level.SEVERE, null, ex);
        }
        SwingUtilities.invokeLater(new Runnable() {

            @Override
            public void run() {
                JFrame frame2 = new JFrame("Frame 2");
                frame2.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame2.getContentPane().add(new JLabel("Hello in frame 2"));
                frame2.pack();
                frame2.setLocation(200, 200);
                frame2.setVisible(true);
                isThereReallyEDT();
            }
        });
    }

    private void isThereReallyEDT() {
        dateRun = new java.util.Date();
        System.out.println("                         Time at : " + sdf.format(dateRun));
        if (EventQueue.isDispatchThread()) {
            System.out.println("EventQueue.isDispatchThread");
        } else {
            System.out.println("There isn't Live EventQueue.isDispatchThread, why any reason for that ");
        }
        if (SwingUtilities.isEventDispatchThread()) {
            System.out.println("SwingUtilities.isEventDispatchThread");
        } else {
            System.out.println("There isn't Live SwingUtilities.isEventDispatchThread, why any reason for that ");
        }
        System.out.println();
    }

    public static void main(String[] args) {
        IsThereEDT isdt = new IsThereEDT();
    }
}

abstract class AccurateScheduledRunnable implements Runnable {

    private ScheduledFuture<?> thisThreadsMonitor;

    public void setThreadMonitor(ScheduledFuture<?> monitor) {
        this.thisThreadsMonitor = monitor;
    }

    protected long getExecutionTime() {
        long delay = -1 * thisThreadsMonitor.getDelay(TimeUnit.MILLISECONDS);
        return delay;
    }
}
于 2012-03-26T14:18:54.533 に答える