63

私は最近、Java での GUI プログラミングの基礎を学び、探求し始めました。

しばらくプログラミングをしていたので、バックエンドの作業や作業しか行っていませんでした。その結果、ユーザー インターフェイスに最も近いのはコマンド コンソールです (恥ずかしいことです)。

私は Swing を使用しています。私が収集できる限り、その拡張により、AWT も使用しています。

私の質問は、次のコードに基づいています。

java.awt.EventQueue.invokeLater(new Runnable() {
    public void run() {
        new frame.setVisible(true);
    }
} );

この奇妙なコードを完全に理解したいと思っており、「イベントディスパッチスレッド」という用語に何度も出くわしたため、しばらくこれを調査してきました。私が間違っている場合は訂正してください。複数のスレッドを使用することと、Java Swing がそれらのスレッドを解釈する方法に関係しています。上記のコードは、ウィンドウを作成する前にすべてのスレッドが「安全」であることを確認するために使用されるため、invokeLater?

私はそれを読んだ:

「イベントディスパッチスレッドからフレームで動作するメソッドのみを呼び出すことができます」

また、特定の状況下でのみ、メイン メソッドからフレームで動作するメソッドを呼び出すことができます。

誰かがイベントディスパッチスレッドとは何かを明確にしてくれませんか?

複数の実行スレッドとどのように関連し、それらのスレッドが main メソッドから呼び出されるのは安全ではないのでしょうか? また、なぜこの invokeLater が必要なのですか?

ウィンドウを他のオブジェクトとして作成することはできませんか?

これらの関係とアイデアを把握していないため、研究で少し障害が発生しました。

余談ですが、私は深い理解に基づいて自分の知識を基にしたいと思っています。これが全体的な最良の結果につながり、結果として最良のプログラムにつながると信じているからです。何かがどのように機能するかを深く理解している場合は、コードにオウム返しするだけでなく、ヒントや微調整を効果的に使用できるので、恐れずにさらに詳細な説明を提供して知識を広げてください.

ありがとうございました。

4

2 に答える 2

72

イベント ディスパッチ スレッドは、AWT によって管理される特別なスレッドです。基本的に、これは無限ループで実行され、イベントを処理するスレッドです。

およびメソッドはjava.awt.EventQueue.invokeLaterjavax.swing.SwingUtilities.invokeLaterイベント キューで実行されるコードを提供する方法です。マルチスレッド環境で安全な UI フレームワークを作成するのは非常に難しいため、AWT の作成者は、GUI オブジェクトの操作を単一の特殊なスレッドでのみ実行できるようにすることにしました。すべてのイベント ハンドラーはこのスレッドで実行され、GUI を変更するすべてのコードもこのスレッドで動作する必要があります。

現在、AWT は通常、別のスレッドから GUI コマンドを発行していないことをチェックしません (C# の WPF フレームワークはこれを行います)。つまり、多くのコードを記述しても、これにほとんど依存せず、問題に遭遇しない可能性があります。ただし、これにより未定義の動作が発生する可能性があるため、最善の方法は、常に GUI コードがイベント ディスパッチ スレッドで実行されるようにすることです。invokeLaterこれを行うメカニズムを提供します。

古典的な例は、ファイルのダウンロードなどの長時間実行される操作を実行する必要がある場合です。したがって、スレッドを起動してこのアクションを実行し、完了したらinvokeLater、UI を更新するために使用します。使用せずinvokeLaterに UI を直接更新した場合、競合状態が発生し、未定義の動作が発生する可能性があります。

ウィキペディアに詳しい情報があります

また、AWT の作成者がツールキットをマルチスレッド化しない理由に興味がある場合は、こちらの記事を参照してください。

于 2011-08-27T20:39:35.493 に答える
13

EventDispatchThread(EDT)は、Swing GUI および *Swing の関連イベント( Swing JComponentsの作成/変更/更新など) 用に予約された特別なスレッドです

BackGround TasksからのGUI へのすべての出力は、同期されたオブジェクトからinvokeLater()Runnable#Threadにラップする必要があります。invokeAndWait();

于 2011-08-27T20:54:26.800 に答える