web-dev-qa-db-ja.com

Javaイベントディスパッチスレッドの説明

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

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

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

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

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

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

私はそれを読んだ:

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

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

イベントディスパッチスレッドが何であるかを誰かが明確に教えていただけますか?

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

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

私はこれらの関係やアイデアを把握していないので、研究で少し障害になりました。

副次的な注意点は、全体的な結果が最高になり、結果としてプログラムが最高になると確信しているため、知識を詳細な理解に基づいて作成することです。何かがどのように機能するかを詳細に理解している場合は、ヒントと調整をコードに戻すだけでなく、効果的に使用できます。そのため、追加の詳細な説明を与えて知識を広げることを恐れないでください。

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

54
linuscash

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

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

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

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

ウィキペディアには詳細情報があります

また、なぜAWTの作者がツールキットをマルチスレッド化しないのか興味があるなら、 here は良い記事です。

59
luke

EventDispatchThread(EDT)は、Swing GUIおよび* Swingの関連イベント(例:作成/変更/更新 Swing JComponents 、質問の詳細 here および here

_BackGround Tasks_、_Runnable#Thread_からGUIへのすべての出力は、同期オブジェクトからinvokeAndWait();への invokeLater() にラップする必要があります

12
mKorbel