| ページ一覧 | ブログ | twitter |  書式 | 書式(表) |

MyMemoWiki

イベントディスパッチスレッド

提供: MyMemoWiki
ナビゲーションに移動 検索に移動

イベントディスパッチスレッド

GUIスレッド

「ほとんどすべてのGUIツールキットはシングルスレッドのサブシステム(single-threded subsystem)として実装されています。すなわちすべてのGUI活動が一つのスレッドに拘束されています。」

「特に意識的に完全にシングルスレッドのプログラムを書かないかぎり、普通のGUIアプリケーションでは、アプリケーションのスレッドとGUIのイベントスレッド、少なくともこの二つのスレッドが動きます。」

「昔はGUIのアプリケーションそのものがシングルスレッドで、GUIのイベントはアプリケーションのメインスレッドの中の"メインイベントループ(main event loop)” と呼ばれるループの中で処理されました。今日のGUIフレームワークはほんの少しだけ違って、イベントディスパッチスレッド(event dispatch thread,EDT)と呼ばれる、GUIイベントを処理する専用のスレッドを作ります。」

Java並行処理プログラミング ―その「基盤」と「最新API」を究める―


Swing のイベントハンドリング

  • Swing のイベントハンドリングコードは、イベントディスパッチスレッドと呼ばれる特別なスレッド上で実行されます。
  • ほとんどのコードは、Swingのメソッドを同様にこのスレッドで、呼び出します。
  • これは、大抵のSwingオブジェクトのメソッドが、スレッドセーフでないため、必要です。

スレッドセーフでないメソッドの呼び出し

  • いくつかのSwingコンポーネントメソッドはスレッドセーフとAPI仕様に記されています。
  • これらは、どんなスレッドからでも安全に呼び出せます。
  • その他のSwingコンポーネントメソッドは、イベントディスパッチスレッドから呼び出す必要があります。

プログラムが、このルールを無視すると、ほとんどの場合きちんと機能するのに、予測や再現性のないエラーが発生しやすくなります。

コードがイベントディスパッチスレッド上で実行されているか

  • 短いタスクとして、コードがイベントディスパッチスレッド上で実行されているかを考慮することは実用的です。
  • ほとんどのタスクは、例えば、ActionListener.actionPerformedのような、イベントハンドリングメソッドとして呼び出されます。
  • 別のタスクは、invokeLater や invokeAndWait を使ってアプリケーションによりスケジュールされます。
  • コードがイベントディスパッチ上で動いているか確認するには、javax.swing.SwingUtilities.isEventDispatchThreadを呼び出します。

コントロール不能のイベントを中止したり、ユーザーインターフェースが無反応にならない為に、イベントディスパッチスレッド上のタスクは、すばやく完了しなければなりません。

import java.awt.BorderLayout;
import java.awt.Dimension;

import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.SwingUtilities;


/**
 * @see http://java.sun.com/docs/books/tutorial/uiswing/components/frame.html
 */
public class JFrameTest {
  privat eJFrame frame;
  public static void main(String[] args) {
    SwingUtilities.invokeLater(
        new Runnable(){
          public void run() {
            JFrameTest jft = new JFrameTest();
            jft.createUI();
          }
        }
    );
  }
  private void createUI() {
    // Windowの生成
    frame = new JFrame("FrameTest");
    // Windowクローズ時にどうするか
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    // ダミーコンポーネント
    JLabel lbl = new JLabel("");
    lbl.setPreferredSize(new Dimension(200,100));
    // フレームにコンポーネントを乗せる
    frame.getContentPane().add(lbl, BorderLayout.CENTER);
    // サイズ調節
    frame.pack();
    // 表示
    frame.setVisible(true);
    
    // debug イベントディスパッチスレッドか?
    System.out.println("EventDispatchThread ? " + SwingUtilities.isEventDispatchThread());
  }
}