argius note

プログラミング関連

AWTスレッドについてのメモ

ここでも触れていますが、JavaGUIを使ったアプリケーションでは、GUI(AWT/Swing)の描画に関連する処理は、専用のスレッドから実行すべきです。これらのスレッドは、Thread.getName()が"AWT"で始まる名前になっています。
良く言われるのは、mainメソッドで"JFrame.setVisible(true)"などでアプリケーションを開始する際には、イベントディスパッチスレッド(EventDispatchThread)から実行するようにしましょう、というものです。

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

こうすることで、AWTのイベントキューに処理が追加され、GUIの処理がひとつずつ順番に処理されます。

まず、イベント処理の中で新たにスレッドを生成している場合は、GUIの処理を行う場合に再びイベントディスパッチスレッドに制御を移す必要があります。また、I/O関連のオブジェクトを操作する場合、当たり前ですがスレッドをまたぐと処理が正常に行えないことがあります。

final InputStream is = new FileInputStream("file");
SwingUtilities.invokeLater(new Runnable() {
    public void run() {
        try {
            is.read(); // already closed!?
        } catch (IOException ex) {
            ex.printStackTrace();
        }
    }
});
is.close();

で、今回これを書いたきっかけは、これに似たようなことをやってしまったからでした。
追記:上記の例で、invokeLater()の代わりにinvokeAndWait()を使うという手もありますが、こちらはイベントディスパッチスレッドからは呼び出せないようになっています。