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が終了しないことが保証されています。