AWT のスレッドの問題

リスナーとスレッド

特に断りのないかぎり、すべての AWT リスナーはイベントディスパッチスレッド上で通知されます。ディスパッチ中に任意のスレッドからリスナーを追加/削除しても安全ですが、変更はその後の通知のみに影響します。
たとえば、キーリスナーが別のキーリスナーから追加された場合、新しく追加されたリスナーにはその後のキーイベントのみが通知されます。

自動シャットダウン

Java™ 仮想マシン仕様」セクション 2.17.9 および 2.19 によれば、Java 仮想マシン (JVM) は最初は単一の非デーモンスレッドで起動し、通常このスレッドが何らかのクラスの main メソッドを呼び出します。仮想マシンは、次の 2 つのうちのいずれかが発生した場合にすべてのアクティビティーを終了し、仮想マシン自身を終了します。

これは、アプリケーション自身がスレッドを開始しない場合、JVM は main が終了するとただちに終了することを意味します。ただし、java.awt.Frame を作成して表示する単純なアプリケーションの場合にはこれは当てはまりません。

        public static void main(String[] args) {
            Frame frame = new Frame();
            frame.setVisible(true);
         }
その理由は、AWT が、AWT または Swing コンポーネントがトリガーできるイベントを処理するために、非同期イベントディスパッチ機構をカプセル化するからです。この機構の正確な動作は実装によって異なります。具体的には、内部的な目的で非デーモンのヘルパースレッドを開始できます。実際に、上記の例ではこれらのスレッドが終了を妨げています。この機構の動作に適用される制限は、次のもののみです。 3 番目の制限の意味は次のとおりです。 すべてのコンポーネントが表示不可になった場合に、非デーモンヘルパースレッドが終了するかどうか、またいつ終了するかは実装に依存します。実装固有の詳細については後述します。

実装依存の動作。

1.4 より前では、ヘルパースレッドは決して終了しませんでした。

1.4 から、4030718 の修正の結果、この動作は変更されました。現在の実装では、次の 3 つの条件が満たされた場合、AWT はそのすべてのヘルパースレッドを終了し、アプリケーションが正常に終了できるようにします。

したがって、System.exit を呼び出さずに正常に終了したいスタンドアローン AWT アプリケーションは、次を確認する必要があります。 これらの推奨事項に従うアプリケーションは、通常の条件下では正常に終了しますが、あらゆる場合に正常に終了することが保証されているわけではありません。例を 2 つ次に挙げます。 一方、アプリケーションがすべてのコンポーネントを表示不可にしたあとでも JVM が実行を継続することを必要とする場合は、永遠にブロックする非デーモンスレッドを開始する必要があります。
        <...>
        Runnable r = new Runnable() {
            public void run() {
                Object o = new Object();
                try {
                    synchronized (o) {
                        o.wait();
                    }
                } catch (InterruptedException ie) {
                }
            }
        };
        Thread t = new Thread(r);
        t.setDaemon(false);
        t.start();
        <...>
Java™ 仮想マシン仕様」では、このスレッドが終了するまで JVM が終了しないことが保証されています。