• ベストアンサー
※ ChatGPTを利用し、要約された質問です(原文:イベントディスパッチングスレッドの振る舞いについて)

イベントディスパッチングスレッドの振る舞いについて

このQ&Aのポイント
  • イベントディスパッチングスレッドを用いてコンポーネントに文字列を表示する処理が思った通りに動作しない理由について説明します。
  • invokeLaterメソッドを使用して複数のイベントをイベントディスパッチングスレッドに格納し実行する場合、最後に格納されたイベントしか実行されず、途中のイベントは無視されます。
  • この動作は、イベントキューに新しいイベントが追加されると、すでに実行中のイベントが完了するまで待機するためです。そのため、途中のイベントは実行される前に新しいイベントが追加され、無視されてしまいます。

質問者が選んだベストアンサー

  • ベストアンサー
  • kacchann
  • ベストアンサー率58% (347/594)
回答No.1

自信なし&カン --- たとえばLabel#setText()は イメージ的には setText(String text){ this.text=text;//…a repaint();//…b } となっているような気がします。 また、repaint()は イメージ的には repaint(){ //イベントキューに「再描画イベント」を入れる invokeLater(Event.UPDATE); } となっていると思います。 これがすべてだと思います。 --- さて、ここで setText()をS(注:Sはaとbから成る。上記参照), 「再描画イベント」をU と書くことにします。 そして (invokeLaterを使うなどして)イベントキューにSを3つ放り込んだとします。 するとキューの状態は SSS となります。(※左側がキューの先頭) やがてイベントスレッドで先頭のSが処理されます。 すなわち、まずaが処理され、次にbが処理されます。 bは「イベントキューへUを追加」にほかならないので、 この時点でのキューの状態は SSU となります。 ・ ・ と考えていくと、最後にはキューの状態は UUU となります。 --- この時点で、a(textの変更)は3度起こりましたが、 描画はまだ一度も起こっていません。

__tanpopo__
質問者

お礼

kacchann様へ ご回答ありがとうござした。 質問を投稿して以来いろいろ試してみたのですが、 kacchann様のご推測と同じような結論に至っておりました。 といいますのは、例えば、イベントディスパッチングスレッドによってinvokeLaterに、Runnableオブジェク トのrun()中にThread.sleep(1000)とsetText("newText"+i)を実装した ものを指定してinvokeLaterを10回実行させて10個のRunnable オブジェクトをイベントキューに格納させた ところ、確かに、イベントディスパッチングスレッドは個々のイベント を処理しているらしく、約10秒経過してからいきなりコンポーネント に「newText10」と表示が反映されました。また、 イベントディスパッチングスレッドによってinvokeLaterを実行させて イベントキューにRunnableオブジェクトを複数個格納させてから イベントディスパッチングスレッドにRunnableオブジェクトを処理 させると、質問のような現象が起きるのですが、もし他の任意の スレッド(例えばinvokerThreadと名づけましょうか)を作成してそのス レッドにRunnableオブジェクトを作成させてinvokeLaterを実行させると、イベントディスパッチングスレッドはinvokerThreadからの一つの Runnableオブジェクトだけを処理するだけでよいので、処理ごとに setText()の内容が反映されるようになりました。 つまり、イベントキューにイベントが「複数個」ある状態で、イベント ディスパッチングスレッドにキューのイベントを処理させると、質問の ような現象を起こし、イベントキューにイベントが「1つ」しかないと きはイベントディスパッチングスレッドは、イベントを処理後すぐに 処理内容がコンポーネントに反映されるようにするようです。

全文を見る
すると、全ての回答が全文表示されます。

関連するQ&A

  • インターフェイスの使い方がわかりません(初心者です)

    Javaを始めたばかりの初心者です。 「やさしいJava」を買って一通り学んだのですが、 インターフェイスの使い方がよくわからず、困っています。 インターフェイスを実装することでインターフェイスが持つメソッドがすべて定義されてることが保障される、 というのはわかるんですが、そのことがどうして有用なのでしょう? また、具体的にはスレッドを扱うときにRunnableインターフェイスを実装する理由がわかりません。 Threadクラスのオブジェクトを作成するときに、 Runnableを実装したクラスのオブジェクトの変数を 引数にしないといけないんですよね? このとき、Runnableインターフェイスが 「runメソッドが定義されていなければならない」 とだけいうものだったとしたら、 Runnableを実装してなくてもrunメソッドさえ定義してあれば 実行できそうな気がするんですが・・・

    • ベストアンサー
    • Java
  • Runnableのインスタンス化について

    下記のコードについてです。 Runnableがインスタンス化されていますが、 どうしてそれが可能なのかが分かりません。 分からない点は 1.Runnableはインタフェースであるから、本来、直接インスタンス化は不可能であるはず。 2.しかし、Runnableはクラスライブラリjava.langパッケージに含まれている。 だからインスタンス化は可能なのかもしれない。 3.あるいは、下記のコードではメソッド内の無名クラスであるから、「new Runnable(){」の 部分でスーパークラスとしてのRunnableを継承したサブクラスを生成しているのかもしれない。 アドバイスをよろしくお願い致します。 public class Main{ public static void main(String[]args){ Runnable task = new Runnable(){ public void run(){ System.out.println("run"); } }; Thread thread = new Thread(task){ public synchronized void start(){ System.out.println("start"); } }; thread.start(); } }

    • ベストアンサー
    • Java
  • SwingとEDT(イベントディスパッチスレッド)

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

  • 310-035の参考書の中にあるThreadとRunnableの説明

    310-035の試験を1か月程勉強中です。スレッドについて頭がゴチャゴチャになってしまいました。 スレッドのインスタンス化ですが、 Threadを継承した場合は単純に Thread t = new Thread() でよいが、 Runnableを実装した場合は、 1行目// MyRunnable r = new MyRunnable(); 2行目// Thread t = new Thread(r) とする。とあります。 説明として、「Runnableの場合はスレッド自身のrun()メソッドではなく独自に定義したrun()メソッドを使用するようにするため」とあるのですが、何をいわんとしてるのか、この説明の意味がわからないのです。。 「スレッド自身のrun()メソッド」「独自に定義したrun()メソッド」って何のことを指してるんでしょうか。 「Threadを継承した場合」はオーバーライドしているので「スレッド自身のrun()メソッド」を見てるってことでしょうか。?? それと、どうしてRunnableの場合は、Threadをextendしてないのに急に2行目のところでThread が現われるんでしょうか。 アドバイスを頂けると助かります。宜しくお願いします。

    • ベストアンサー
    • Java
  • Javaにおけるイベント処理

    JFrame  SpritPanel   SpritPanel    JPanel     JButton A     JButton B     JButton C    JList A   SpritPanel    JList B    JTable C という構成で、JButton A をクリックしたらJList AにJButton A用のなんらかのリストを表示し、JButton BをクリックしたらJList BにJButton B用のなんらかのリストを表示し、・・・ と1つGUI部品で発生するイベントで1つまたは複数のGUI部品の更新処理を行いたいのですが、イベントリスナをどこに実装させて、どこに更新処理を書くかで迷います。 例えば、押されるJButton Aにイベントリスナーのメソッドを実装し、そこで処理を書く場合はJList Aをこのメソッド内から見えるようにしなけなくて、それをするためにインスタンスを渡したりするのが面倒に感じています。 様々なGUI部品やパネルで構成され、イベントが起きたら複数のGUI部品が更新が必要となるようなGUIアプリケーションを作る場合、どのようにイベントを処理させるのが王道なのでしょうか。 うまく質問できないので、質問内容に不明な点があれば補足いたします。

    • ベストアンサー
    • Java
  • インターフェイスと抽象クラス

    なかなか理解が難しくて苦しんでいます。 で自分なりに理解したのですが、 抽象クラス→内容に決まっているメソッドと決まっていないメソッドがある場合に決まっていないメソッドを あとからオーバーライドするだけでスーパークラスで定義したすべてのメソッドを利用できる。 これでただしいでしょうか? で、インターフェイスなのですが、この抽象クラスとそっくりなんですが、 (1)変数は定数になる(強制static)(2)メソッドは名前のみの宣言(内容は記述できない) と言うことで、かなり???なのです。 何のために・・・???記述するんでしょうか?? ただひとつメリットがあるとしたら、インターフェイスを実装すると、インターフェイスの配列でインスタンスを 生成出来るということぐらいでしょうか。 そこでちょっとお門違いの疑問かもしれないんですが、 Runnable、やMouselistenerはメソッドの内容が書かれていないのに、 なぜ機能を持たせることが出来るのでしょう??? 認識違い、間違い等ありましたら、教えてください よろしくお願いいたします。

    • ベストアンサー
    • Java
  • C#のdelegateをC++とjavaで?

    C#のデリゲードを javaとC++でできないでしょうか。 ただし、質問内容を勘違いされそうなので、求めている内容と、 求めていない内容を、詳しく 書きますと。 インタフェース委譲を使った例は、求めていません。 あらかじめ、委譲先に静的に仕組みを 作っておかなく手も、C#のデリゲードのように、シグニチァが同じなら 委譲先をはめ込めれるのが欲しいです。 単なる関数ポインタの例は、求めて いません。 C#でdelegate型を引数にとる ところに、あるインスタンスの メソッドを渡すと。 どのインスタンスのどのメソッドかまで、 認識して、コールバックできます。 関数ポインタでは、これができない。 STLの関数オブジェクトとか、古い感じの情報にヒントがあるか。調べてみましたが。よくわかりませんでした。 結局、この関数オブジェクトは、僕が求めているモノとは、違うような気がします。 よくわかりませんが。 欲しいのは、どのインスタンスのどのメソッドかまでを特定して、 記憶できる型をどうやって javaや、C++で実装できるか。 それをインタフェース委譲のように、 委譲先にあらかじめ、仕込んでおくことなしに。 ただ、メソッドのシグニチァが同じであるだけで、どのインスタンスのどのメソッドかまでを特定して記憶できる C#のデリゲードのような型を。 特殊なコンポーネントを利用せず。 標準的な言語構文のみをつかって、 どのようにしたら、 javaや、C++で、実装できるか? です。 詳しい方が、いらっしゃいましたら、 教えてください。

  • ActiveXDLL(VB)にウィンドウハンドルを受け取るメソッドを用意したい

    VB6で作成したActiveXDLLに、ウィンドウハンドルを渡すためのメソッドを実装したいと思います。 ActiveXDLLを使用するクライアントはCで作成しており、クライアント側で表示するウィンドウのボタンを押下した際にActiveXDLLのCOMコンポーネントをインスタンス化して、クライアントのウィンドハンドルをCOMコンポーネントに渡したい次第です。 VBでウィンドウハンドルを受け取るFunctionを作成したことがなく、また調べてみたものの解決策を見出すことができませんでしたので、よい方法や参考HPがあれば教えていただきたいと思っております。 よろしくお願いいたします。

  • Python3でのメタプログラミングについて

    下記の Ruby スクリプトと同じことを Python で行う場合、どのように実装すればいいでしょうか? <前提> ・メソッドを Klass クラスに実行時に動的に追加する。 ・追加したメソッドの動的削除、変更は必要ない。 ・メソッド定義は、Python のオブジェクトではなく単なる文字列。 ・メソッド内部から Klass クラス内のインスタンス変数にアクセスする。 ・Klass クラスや Klass インスタンスを扱う処理から、動的に追加したメソッドを呼び出す。 ・追加したメソッドはシングルトンメソッドである必要はない。 <目的> Klass クラスのカスタマイズ機能をメソッド定義文として外部に保存しておいて、実行時に呼び出して機能を拡張するような目的です。Klass クラスはめったに変更されないもの、カスタマイズ機能(メソッド定義文)はよく変更されるもの、という切り分けをしたいため、単純に多重継承や MixIn はしたくないです。(上手い方法があればいいのですが…) #!/usr/bin/env ruby # coding: utf-8 # 文字列のメソッド定義 $user_funcs = [' def user_foo() puts "foo" * @x end ', ' def user_bar() puts "bar" * @x end '] # ↑本来は文字列として外部DBに記録されている。 # ---- # # 拡張したいクラス # class Klass # インスタンス変数を持つ def initialize @x = 3 end attr_accessor :x # 文字列で定義されたメソッドを追加 $user_funcs.each do |f| eval f end end # ---- # # 呼出方法 # obj = Klass.new # 追加されたメソッド(user_から始まる名前)を列挙しながら実行する # => どんな定義がされていても、命名規則さえ守っていれば呼び出し側はそのメソッド名を知る必要はない。 obj.methods.select {|m| /^user_/ =~ m }.each do |m| eval "obj.#{m}" end # 追加されたメソッドはシングルトンメソッドではなく、あくまでもインスタンスメソッドである。 obj2 = Klass.new # インスタンス変数の書き換え obj2.x = 4 # インスタンスメソッドの書き換え def obj2.user_bar() puts "hoge" * @x end obj2.methods.select {|m| /^user_/ =~ m }.each do |m| eval "obj2.#{m}" end

  • 4人プレイの七並べGAMEを作りたいのですが。初心者です。

    初心者です。宜しくお願いします。 4人プレイで内3人がコンピュータ。というトランプゲーム(七並べ)をつくりたいのですが、3人のコンピュータ自動処理後の 自分で選んでイベント待ち状態?をつくるにはどうしたらいいのかわかりません。 (参考) run(){ while(flag == true){ 1P処理のメソッド();  //COM1   2P処理のメソッド();  //COM2   3P処理のメソッド();  //player   4P処理のメソッド();  //COM3    thread.sleep(3000); かなりはしょっての説明で恐縮ですが、 この3Pの場所で、マウスでカードを選びクリックするまでストップさせたいんです。選んでクリックするとまた4P→1P→2P・・・と動作させたいのですが、どうすればいいのかわからず質問しました。 今の地点の動きは、1Pの処理(3秒)→2Pの処理(3秒)→3Pの処理(3秒内で選んでクリックしないとプログラムストップ)→4Pの繰り返しになっています。3Pの場面でrunメソッド内のwhileのフラグをfalseにしてマウスイベントのメソッドを別フラグでtrueにし、クリックしたらまたrunメソッド内のwhileのフラグをfalseに戻すという処理でかろうじて動いているのですが、普通の方法というか、なにかいい方法教えてください。お願いします。