マルチスレッドプログラムがあり、1つのスレッドで複数のスレッドを監視しています。機能は次のように設計されています。
メインプログラムが開始を行い、ウォッチャースレッドを開始します。voidMain()で、次の行があります。
Runtime.getRuntime().addShutdownHook(new Thread(new ShutdownThread(), "Exit Listener"));
ウォッチャースレッドを開始しない場合、プログラムの終了時にShutdownThreadが呼び出されますが、デッドループのあるウォッチャースレッドを開始すると、ShutdownThreadが呼び出されません(そのスレッドでメッセージを出力します) 。それは非常に奇妙です。説明はありますか?
ウォッチャースレッドは次のようなものです。
public void run(){
boolean running=false;
thread a=new thread(...); //Do the same thing for b, c, d...
while(true){
if (a.isActive()){
if (running)
thread a= new thread(...);
a.start();
running=true;
}
Thread.sleep(1000); //try catch block...
}
私が欲しいのは、終了シグナルを受け取ると、shutdownThreadが実行され、フラグを設定してすべてのスレッドに割り込み、スレッドが割り込むのを待つか、残りのスレッドを強制終了できるようにタイムアウトする、正常なシャットダウンです。すべてのスレッドが割り込みをキャッチし、フラグが設定されているかどうかを確認できます。設定されている場合は、shutdownThreadを中断して、それ自体を終了します。代わりに、私が見ているのは、すべてのスレッドがそれ自体で終了していて、クリーンアップをまったく行っていないことです。
信号を使ってみませんか?そのための優れたクロスプラットフォームコードはありますか?
その場合、setUncaughtExceptionHandlerも機能しません。テストを行ったところ、ハンドラーがまったく呼び出されていないことがわかりました。どうしてか分かりません。ハンドラーのコードは次のとおりです。
public static class ErrHandler implements Thread.UncaughtExceptionHandler{
public final void uncaughtException(Thread t, Throwable e) {
Error(t + "died, threw exception: " + e);
}
}//this is in public class globals
私はそれを使用してフックします
producer.setUncaughtExceptionHandler(Globals.errhandler);
私のコードにあり、代わりに元のe.printStack()のみが表示されます。親スレッドでも、それ自体でも、オーバーライドできないようです。これはとてもイライラします。エントリをキューに入れて、他の場所で読み取ることを考えています。少なくともそれはうまくいくかもしれません。
ああ、全体の目的は、実行時の例外が原因でスレッドのいずれかが停止した場合に、ウォッチャースレッドが例外が十分に致命的であるかどうかを確認し、そのスレッドを再起動するか、完全に終了するかを決定することです。同時に、ユーザーがプログラムを終了したときに、プログラムを正常に終了するようにします(割り込みがセーバースレッドに送信され、結果がダンプされてから、割り込みを返し、終了する準備ができていることを通知します)。