• 締切済み

SwingとEDT(イベントディスパッチスレッド)

多くのサイトを見て、色々考えているのですが、イマイチ理解が及びません。以下のような風に思っていていいのでしょうか。 ・Swingではメインとなるmainスレッド(表現は正しくないかもしれない)と、描画関係のイベントを実行するイベントディスパッチスレッドで出来てる。 ・描画関係のイベント(正確にはコンポーネントの可視化及び可視化したコンポーネントの描画)はイベントディスパッチスレッド上で実行しなければならない。 ・SwingUtilities.invokeLaterを使うことによってその中身のプログラムをイベントディスパッチスレッドで実行してくれる...? →setVisible(true)やsetText("")など全てSwingUtilities.invokeLaterを使って記述しなければならない.....???(面倒すぎじゃないでしょうか) ・Swingでのマルチスレッドを行うにはSwingWorkerを使う(ことは見つけているのですが、まずEDTについて理解しないと先に進めないと思い、まだあまりこれの内容は調べていません) ・描画系の命令を実行しないのならば、別スレッドを作成して使用しても良い....? こんなところでしょうか。 しかし、このとおりだとすると今までの自分の書いてきたプログラムは間違いだらけ(特に「全ての描画系命令をSwingUtilities.invokeLaterを使いEDTで実行する」点)になってしまいます。 ちゃんとした理解をしておきたいので、わかりやすい説明でも、上記の間違っている点でもご教示願います。

  • dossi
  • お礼率40% (11/27)
  • Java
  • 回答数1
  • ありがとう数4

みんなの回答

  • SN1701
  • ベストアンサー率76% (16/21)
回答No.1

書いてあること自体は、一部を除いて、ほぼ間違っていないと思います。 ただ、自分の書いたコードがイベントディスパッチスレッドで動いているのかそうでないのか、よくわからなくて混乱されているような印象を持ちました。 Swingは、シングルスレッドの設計です。Swingコンポーネントに対する呼び出しは、イベントディスパッチスレッド(EDT)上で行われる必要があります。例外は、repaint()です。 マウス、キーボード操作などのイベントも、すべてEDT上で処理します。 アプリケーションの処理はイベントに対する反応として記述します。これが、イベント発生時に呼び出されます。イベントは1つのスレッド上で順番に処理されます。 こういう設計は、イベント駆動といって、プラットフォームを問わず、GUIを持つアプリケーション用の仕組みとして一般に見られるものです。 http://ja.wikipedia.org/wiki/%E3%82%A4%E3%83%99%E3%83%B3%E3%83%88%E9%A7%86%E5%8B%95%E5%9E%8B%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9F%E3%83%B3%E3%82%B0 > Swingではメインとなるmainスレッド(表現は正しくないかもしれない)と、描画関係のイベントを実行するイベントディスパッチスレッドで出来てる。 Javaでmainスレッドというと、最初に作られるスレッドですが、mainスレッド自体はとくに必要無いので、終わってしまってもかまいません。実際、自分の作ったアプリケーションでも、用が済んだらmainスレッドはすぐに終了してしまいます。EDTが重要です。 ただ、シングルスレッドの設計とはいえ、Swingは、EDT以外のスレッドも内部で使用します。 例えば、java.awt.Toolkitで画像を読み込むとバックグラウンドのスレッドで読み込まれます。 画像の読み込みには一般的に時間がかかるからです。 > 描画関係のイベント(正確にはコンポーネントの可視化及び可視化したコンポーネントの描画)はイベントディスパッチスレッド上で実行しなければならない。 そうです。描画というより、Swingコンポーネント関係の操作をEDT上で行う必要があります。 コンポーネントの描画もEDT上で行われます。 可視化というのが何を指すのか、ちょっと意味がとれませんでしたが… setVisible(true) のことでしょうか? ということなら、これもその通りです。 > SwingUtilities.invokeLaterを使うことによってその中身のプログラムをイベントディスパッチスレッドで実行してくれる...? そうです。invokeLaterに渡したRunnableオブジェクトのrunメソッドを呼ぶというイベントが、イベントキューに入れられます。イベントが処理されるとrunメソッドが呼ばれます。 そのため、即座に実行されるわけではなく、実行が予約されるような動きであると思ってください。 > →setVisible(true)やsetText("")など全てSwingUtilities.invokeLaterを使って記述しなければならない.....???(面倒すぎじゃないでしょうか) EDT以外から、setText等のSwingコンポーネントの操作をしたいのならその通りです。 しかし、マウス、キーボードイベントのようなイベント処理はそもそもEDT上で動くわけですから、そこでsetText等をする分には、invokeLaterを使っていなくても問題ないです。 そういう意味では、「全て」ではありません。あくまで、EDT以外のスレッドからの場合です。 > 面倒すぎじゃないでしょうか すべてマルチスレッドで同期をきちんと考える面倒さと、全部をEDTでやる面倒さ、どっちが面倒か、ですね。 自分としては、用もないのにマルチスレッドで処理したくはありません。 マルチスレッドで、破綻無く動かすのはなかなか面倒です。 SwingWorkerについてですが、長時間の処理を実行したいとき、EDTで処理してしまうとイベントディスパッチループへ処理を返さないことになり、他のイベントを処理できなくなります。画面は固まって、応答なしになります。 となると、重い処理は別のスレッド(作業用スレッド)で実行したくなります。問題は画面へのアクセスです。プログレスバーのように、処理中の状況を画面に表示したいことがあると思います。しかし、EDT以外のスレッドからSwingコンポーネントにはアクセスできません。描画処理はイベントを送ってEDT側で処理する必要があります。 SwingWorkerは、この手の作業用スレッドとEDTとのやりとりや、作業スレッドの再利用など、面倒なところを助けてくれるものです。 便利ですが、使わなければいけないというわけではありません。ルールを守っていれば、自分で同じような仕組みを書けばいいので。でも、便利なので使いますけど。 > 描画系の命令を実行しないのならば、別スレッドを作成して使用しても良い....? もちろんです。問題になるのは、描画系というかSwingコンポーネント関係です。 ただし、結果を表示したいとなったら、EDTに頼む必要があります。 見えないSwingの中でやっていることがいろいろあるので、なかなか、何がどこのスレッドで、どういうタイミングで動くのかイメージするのが難しいかもしれません。

dossi
質問者

お礼

細かく丁寧にありがとうございます。おかげで私の中で大きく勘違いをしていることに気づくことができました!! 今まで私はソースコードとして書いたプログラムをどのスレッドが行っているのか把握していませんでした。イベントリスナーによって実行されるプログラムなどはメインスレッドが行っているものだと思っていました。そのため理解に苦労していたのだと思います。 詳しい説明をありがとうございました! これからはSwingのスレッドポリシーに則ってプログラムを書こうと思います。

関連するQ&A

  • invokeLaterの逆に

    私は、SwingUtilities.invokeLater(Runnnable doRun)では、イベントディスパッチ・スレッド以外からの描画を伴うリクエストを、AWT-EventDispatchThreadの実行と同期して実行させるための機構だと理解しています。これは描画を伴う処理を描画のタイミングに集約して効率化する機能です。 では、逆にイベントディスパッチ・スレッドの過程で実行していながらも、描画の変化と直接関係ない処理を、イベントディスパッチ・スレッドの描画サイクルの終了後に後回しで行う方法はないのでしょうか?

  • イベントとスレッド

    Java初心者です。 イベントとスレッドに関する質問です。 Swingを使ったアプリケーションを作成しているのですが、 以下のような現象が起きています。 1. ボタンが配置されているダイアログ(A)で、そのボタンを押下する。 2. ボタンを押下したときに実行されるメソッドで、スレッドを作成する。 3. その作成されたスレッドで、JOptionPane#showOptionDialogを実行して、ダイアログ(B)を表示する。 4.(B)が表示されている状態で、別のウィンドウで隠し、再度表示させると、(B)に配置されているボタンが押せなくなる。 4.で(B)のボタンを押せるようにしたいのですが、 うまくいきません。 スレッドとかイベントが関係していると思うのですが、 何しろ初心者なもので、よく理解していません。 実際のプログラムをお見せすることが出来ないので分かりずらいかもしれませんが、何かお気づきのことがあれば 教えて頂けないでしょうか? よろしくお願い致します。

    • ベストアンサー
    • Java
  • SwingWorkerに関して

    このサイトにあるSwingWorkerについて、 このSwingWorkerクラスは、GUIを相対的に描画するためのスレッドという ことなのでしょうか?そうだとしたら、イベントディスパッチ用のスレッド と動作がダブりませんか? 以下のサイトでは説明が詳しくなくプログラムを見ただけでは、以上のよう に考えてしまうのですが、上記のようなプログラムと考えていいのでしょうか? http://terai.xrea.jp/Swing/SwingWorker.html

    • ベストアンサー
    • Java
  • SwingのpaintComponent()メソッドについて

     JAVA初心者です、宜しくお願いします。  参考書で、Swingについて以下のようなコメントを見つけました、ただ何故そうなのかの理由を書いていません。  以下の内容はどのような理由からそうなるのでしょうか。  「Swing コンポーネントでは、メソッドpaintは推奨されていません。  paintComponentをプログラムから呼び出してはいけません。描画をしたい場合は、 paintComponent をオーバー ライドしたクラスの repaint() メソッドを呼び出します。  Swing コンポーネント上に描画するには、 描画したいコンポーネントのクラスを継承したクラスで、 メソッド paintComponent(Graphics g) をオーバーライドし、 パラメータで渡された g に対して Graphics クラスのメソッドで描画をします。  オーバーライドした paintComponent の先頭で、このコンポーネントの土台を描画するために、 super.paintComponent(g) を呼び出しておきます。」  宜しくお願いします。

    • ベストアンサー
    • Java
  • SwingでSwingUtilities.invokeLater()の利用

    はじめまして。Javaビギナーです。 今Swingを利用したチャットアプリを作成しようと色々調べているところなのですが、よくmain()メソッド内にて public static void main(String[] args) { SwingUtilities.invokeLater(new Runnable() { public void run() { // 初期処理 } }); } というのを見かけます。 これは、Swingでアプリを実行する場合に上記のように作成することが一般的なのでしょうか? それとも、マルチスレッドを利用する必要のない場合などは上記のようなコーディングは行われないのでしょうか? 後々の機能拡張などを考えれば、上記のようにコーディングした方が良いのだと思いますが、一般的な利用方法を教えていただければと思います。宜しくお願いします。

  • SwingUtilities.invokeLater(new Runn

    SwingUtilities.invokeLater(new Runnable() {}について 以前質問でgooで教えて頂いた際、以下のようなコードがありました。 どのような効果があるのか教えてください。 APIを見ても理解できませんでした。 また、APIを理解するコツのようなものはあるでしょうか。 ご存知の方がおられましたら教えてください。 ・試してみたこと  重いプログラムを起動させ、実行速度を比べた。------ほとんど同じでした。   public static void main(String a[]) { SwingUtilities.invokeLater(new Runnable() { public void run() { new test(); } }); }

    • ベストアンサー
    • Java
  • javaのswingコンポーネントについて質問です。

    javaのswingコンポーネントについて質問です。 javaをやり始めて2ヶ月ぐらいたちました。 今までアプレットとアプリケーションの両方をやりこちらはできたのですが 「swing」を使用したアプレット(JApplet)だけがアプレットビューアやhtmlで開いても実行できません。 わかるかたできれば教えていただければ幸いです。 追記 実行できないのはソースファイルにJAppletで組んだプログラムだけです。 本に記載されたソースプログラムやインターネットに上がっているソースプログラムを実行してみましたが これらもJAppletを使用したものだけができませんでした。

  • スレッドについて

    JAVAでプログラムを書く上で、Aという処理が終了次第、Bという処理を実行したい場合どうすればいいのでしょうか? ///////////////////////////////////////////////////////////////// 例えば、 ・ファイルにデータを出力する。(例えば、バッチファイルhoge.batとして) その後、すぐに ・そのバッチファイルを実行する命令を書く(Runtime.exec(hoge.bat); ///////////////////////////////////////////////////////////////// このプログラムを実行した場合、スレッドAがファイルにデータを出力し終わる前に勝手にスレッドBが作られ、Runtime.exec(hoge.bat);が実行されてしまいます。正しくスレッドAが終了し終わった後にスレッドBが実行し始めるようにするにはどうすればいいのでしょうか?教えてください。お願いします。

    • ベストアンサー
    • Java
  • マルチスレッドプログラミングについて

    現在DirectXでマルチスレッドを使ってプログラムを組んでいますが、その処理の中で描画のみを切り離してスレッド化しようと思っています。 そこで質問ですが、描画スレッドに渡す処理の個数が多い場合は描画スレッドを2つにして処理する個数も分けたほうが処理は早くなるのでしょうか?

  • プロセスとスレッドの違いについて(Cプログラミングの観点から)

    プロセスとスレッドの違いがしっくりきません。 <プロセス> (1)プログラムの実行単位。Windows や Linux などの汎用 OS 上のアプリケーションは一般にプロセスとして動作している。プロセスは1つ以上のスレッドと、ファイル、ヒープメモリなどのリソースで構成される (2)起動や切り替えのオーバーヘッドが大きい <スレッド> (1)同一プロセス内の複数スレッドを同一メモリ空間上で実行でき、メモリ消費量などが軽減できる。 (2)マルチスレッド処理のプログラミングにおいては、同じデータを複数のスレッドが同時に書き換えることによる不整合に注意し、排他制御を行う必要がある。 等はwiki等調べて理解しています。 何が疑問なのかと申し上げますと、具体的にプログラミングする際に (1)マルチプロセスとマルチスレッド方式では、ソースにどのような違いが出てくるか (2)マルチプロセスとマルチスレッド方式では実行時間がどれだけ変化するか がわからないのです。お仕事で並列処理等について担当されている方などおられましたら、お手数ですがご教授ください。 なお、わかりやすい書籍、webサイト等ありましたらそれも併せて教えていただけると助かります。よろしくお願いします。ちなみに、環境はWindowsXP,VisualC++ExpressEdition2005を使っていますので、UNIXよりはWindowsかつCで動くプログラム例で教えていただけると大変助かります。しかし、当方Javaも多少であれば組めますのでJavaでも構いません。 何卒、よろしくお願い致します。

専門家に質問してみよう