「イベントディスパッチスレッド」の版間の差分
ナビゲーションに移動
検索に移動
(同じ利用者による、間の3版が非表示) | |||
1行目: | 1行目: | ||
− | ==イベントディスパッチスレッド== | + | ==[[イベントディスパッチスレッド]]== |
− | + | [[Java]] | [[Swing]] | [[Category:並行処理]] | |
http://java.sun.com/docs/books/tutorial/uiswing/concurrency/dispatch.html | http://java.sun.com/docs/books/tutorial/uiswing/concurrency/dispatch.html | ||
==GUIスレッド== | ==GUIスレッド== | ||
7行目: | 7行目: | ||
「特に意識的に完全にシングルスレッドのプログラムを書かないかぎり、普通のGUIアプリケーションでは、アプリケーションのスレッドとGUIのイベントスレッド、少なくともこの二つのスレッドが動きます。」 | 「特に意識的に完全にシングルスレッドのプログラムを書かないかぎり、普通のGUIアプリケーションでは、アプリケーションのスレッドとGUIのイベントスレッド、少なくともこの二つのスレッドが動きます。」 | ||
− | 「昔はGUIのアプリケーションそのものがシングルスレッドで、GUIのイベントはアプリケーションのメインスレッドの中の"メインイベントループ(main event loop)” | + | 「昔はGUIのアプリケーションそのものがシングルスレッドで、GUIのイベントはアプリケーションのメインスレッドの中の"メインイベントループ(main event loop)” と呼ばれるループの中で処理されました。今日のGUIフレームワークはほんの少しだけ違って、[[イベントディスパッチスレッド]](event dispatch thread,EDT)と呼ばれる、GUIイベントを処理する専用のスレッドを作ります。」 |
− | + | [http://www.amazon.co.jp/gp/product/4797337206?ie=UTF8&tag=typea09-22&linkCode=as2&camp=247&creative=7399&creativeASIN=4797337206 Java並行処理プログラミング ―その「基盤」と「最新API」を究める―] | |
{{amazon|4797337206}} | {{amazon|4797337206}} | ||
− | ===Swing のイベントハンドリング=== | + | ===[[Swing]] のイベントハンドリング=== |
− | *Swing | + | *Swing のイベントハンドリングコードは、[[イベントディスパッチスレッド]]と呼ばれる特別なスレッド上で実行されます。 |
− | * | + | *ほとんどのコードは、[[Swing]]のメソッドを同様にこのスレッドで、呼び出します。 |
− | * | + | *これは、大抵の[[Swing]]オブジェクトのメソッドが、スレッドセーフでないため、必要です。 |
===スレッドセーフでないメソッドの呼び出し=== | ===スレッドセーフでないメソッドの呼び出し=== | ||
− | * | + | *いくつかの[[Swing]]コンポーネントメソッドはスレッドセーフとAPI仕様に記されています。 |
*これらは、どんなスレッドからでも安全に呼び出せます。 | *これらは、どんなスレッドからでも安全に呼び出せます。 | ||
− | * | + | *その他のSwingコンポーネントメソッドは、[[イベントディスパッチスレッド]]から呼び出す必要があります。 |
− | + | <blockquote>プログラムが、このルールを無視すると、ほとんどの場合きちんと機能するのに、予測や再現性のないエラーが発生しやすくなります。</blockquote> | |
− | *Java Swing 非同期処理の結果をGUIに表示する | + | *[[Java Swing 非同期処理の結果をGUIに表示する]] |
− | === | + | |
− | * | + | ===コードが[[イベントディスパッチスレッド]]上で実行されているか=== |
+ | *短いタスクとして、コードが[[イベントディスパッチスレッド]]上で実行されているかを考慮することは実用的です。 | ||
*ほとんどのタスクは、例えば、ActionListener.actionPerformedのような、イベントハンドリングメソッドとして呼び出されます。 | *ほとんどのタスクは、例えば、ActionListener.actionPerformedのような、イベントハンドリングメソッドとして呼び出されます。 | ||
*別のタスクは、invokeLater や invokeAndWait を使ってアプリケーションによりスケジュールされます。 | *別のタスクは、invokeLater や invokeAndWait を使ってアプリケーションによりスケジュールされます。 | ||
− | *コードがイベントディスパッチ上で動いているか確認するには、javax.swing. | + | *コードがイベントディスパッチ上で動いているか確認するには、javax.swing.[[Swing]]Utilities.isEventDispatchThreadを呼び出します。 |
− | + | <blockquote>コントロール不能のイベントを中止したり、ユーザーインターフェースが無反応にならない為に、[[イベントディスパッチスレッド]]上のタスクは、すばやく完了しなければなりません。</blockquote> | |
===例=== | ===例=== | ||
37行目: | 38行目: | ||
import java.awt.Dimension; | import java.awt.Dimension; | ||
− | import javax.swing.JFrame; | + | import javax.swing.[[JFrame]]; |
import javax.swing.JLabel; | import javax.swing.JLabel; | ||
− | import javax.swing. | + | import javax.swing.[[Swing]]Utilities; |
45行目: | 46行目: | ||
* @see http://java.sun.com/docs/books/tutorial/uiswing/components/frame.html | * @see http://java.sun.com/docs/books/tutorial/uiswing/components/frame.html | ||
*/ | */ | ||
− | public class | + | public class [[JFrame]]Test { |
− | privat | + | privat e[[JFrame]] frame; |
public static void main(String[] args) { | public static void main(String[] args) { | ||
− | + | [[Swing]]Utilities.invokeLater( | |
− | new | + | new [[R]]unnable(){ |
public void run() { | public void run() { | ||
− | + | [[JFrame]]Test jft = new [[JFrame]]Test(); | |
jft.createUI(); | jft.createUI(); | ||
} | } | ||
59行目: | 60行目: | ||
private void createUI() { | private void createUI() { | ||
// Windowの生成 | // Windowの生成 | ||
− | frame = new JFrame("FrameTest"); | + | frame = new [[JFrame]]("FrameTest"); |
// Windowクローズ時にどうするか | // Windowクローズ時にどうするか | ||
− | frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); | + | frame.setDefaultCloseOperation([[JFrame]].EXIT_ON_CLOSE); |
// ダミーコンポーネント | // ダミーコンポーネント | ||
JLabel lbl = new JLabel(""); | JLabel lbl = new JLabel(""); | ||
lbl.setPreferredSize(new Dimension(200,100)); | lbl.setPreferredSize(new Dimension(200,100)); | ||
// フレームにコンポーネントを乗せる | // フレームにコンポーネントを乗せる | ||
− | frame.getContentPane().add(lbl, BorderLayout. | + | frame.getContentPane().add(lbl, BorderLayout.CENTE[[R]]); |
// サイズ調節 | // サイズ調節 | ||
frame.pack(); | frame.pack(); | ||
72行目: | 73行目: | ||
frame.setVisible(true); | frame.setVisible(true); | ||
− | // debug | + | // debug [[イベントディスパッチスレッド]]か? |
− | System.out.println("EventDispatchThread ? " + | + | System.out.println("EventDispatchThread ? " + [[Swing]]Utilities.isEventDispatchThread()); |
} | } | ||
} | } |
2021年3月25日 (木) 14:30時点における最新版
目次
イベントディスパッチスレッド
Java | Swing | http://java.sun.com/docs/books/tutorial/uiswing/concurrency/dispatch.html
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()); } }
© 2006 矢木浩人