SwingUtilities#invokeLaterとはなんじゃらほいさっさ

SwingUtilities#invokeLaterは理解しづらい

SwingのSwingUtilities#invokeLaterについてちょっと調べてみたが、よくわからないのでもっと調べてみた。
SwingのSwingUtilities#invokeLaterがわからなくなってしまうのは、その「後で実行する」という名前に反して「イベントディスパッチャスレッドに処理を依頼する」という使われ方が主だからだ。
もう名前を変えちまえ。
以下にその使われ方をまとめていこう。

構築および始動

Swingオブジェクトはシングルスレッド設計で、単一のスレッド(イベントディスパッチャスレッド)からしかアクセスしてはならないということになっている。
これはSwingコンストラクタおよびsetVisibleも例外ではない。
そのため、時々*1次のようなサンプルを見かける。

public static void main(String[] args) {
  SwingUtilities#invokeLater(new Runnable() {
    public void run() {
      MyFrame frame = new MyFrame();
      frame.setVisible(true);
    }
  });
}

重い処理

時間のかかる処理をSwingのSwingUtilities#invokeLaterに任せ、今キューに入っているイベントをすべて実行した後でイベントディスパッチャスレッドに実行してもらう。
「重い処理を実行する際に使用する」などと紹介されていることがあるが、この処理の実行中に新たなイベントが発生した場合、結局そのイベントはブロックされてしまうのでこの使い方はあまり意味がないのではないだろうか?
それより重い処理は別のスレッドに任せ、Swingオブジェクトにそれを反映するときにだけイベントディスパッチャスレッドにお願いすればいいんじゃないだろうか。
というわけでそれをやってくれるのがJava6から導入されたSwingWorker。


よし、これですっきり整理できた。

*1:「時々」というのは、そうでないサンプルの方が多く見かけるから。これを怠ってもバグが顕在化することは少ないのだろう