4

私はJava /スレッドが初めてで、次のコードのようなものを継承しました。main() が 5 ~ 6 種類のスレッドのみを開始し、^C で終了するコマンド ライン プログラムです。すべてのスレッドを適切に閉じるためにシャットダウンフックを追加し、次のように調整したいと思います。

すべてのスレッドに Shutdown フックと stopThread() メソッドを追加しました (MyWorker クラスのものと同様)。

問題は、^CI を押しても、スレッドの run メソッドからの終了メッセージが表示されないことです。これはバックグラウンドで行われますか、それとも私の方法に何か問題がありますか? また、私が従うべきより良いパターンはありますか?

ありがとう

 public class Main {
     public static MyWorker worker1 = new MyWorker();
     // .. various other threads here

     public static void startThreads() {
         worker1.start();
         // .. start other threads
     }

     public static void stopThreads() {
         worker1.stopThread();
         // .. stop other threads
     }

     public static void main(String[] args)
             throws Exception {

         startThreads();

         // TODO this needs more work (later)

         Runtime.getRuntime().addShutdownHook(new Thread() {
             @Override
             public void run() {
                 try {
                     stopThreads();
                 } catch (Exception exp) {

                 }
             }
         });
     } }

 public class MyWorker extends Thread {
     private volatile boolean stop = false;

     public void stopThread() {
         stop = true;
     }

     public void run() {
         while (!stop) {
             // Do stuff here
         }
         // Print exit message with logger
     } 
}
4

5 に答える 5

10

場合によっては、シャットダウン フックが実行されないことがあります。

最初に留意すべきことは、シャットダウン フックが常に実行されるとは限らないということです。内部エラーが原因で JVM がクラッシュした場合、1 つの命令を実行する機会がなくてもクラッシュする可能性があります。

また、O/S がSIGKILL ( http://en.wikipedia.org/wiki/SIGKILL ) シグナル ( kill -9Unix/Linux の場合) または TerminateProcess (Windows の場合) を送信した場合、アプリケーションは待機することさえせずにすぐに終了する必要があります。あらゆる清掃活動に。上記に加えて、メソッドを呼び出してシャットダウン フックを実行させずに JVM を終了することもできますRunime.halt()

シャットダウン フックは、アプリケーションが正常に終了したとき (すべてのスレッドが終了したとき、またはSystem.exit(0)が呼び出されたとき) に呼び出されます。Ctrlまた、ユーザーが終了を要求した場合 ( + C)、O/S によって発行されたSIGTERM (-9 を使用しない通常の kill コマンド)、またはオペレーティング システムがシャットダウンしている場合など、外部の原因により JVM がシャットダウンしている場合。

于 2016-01-04T07:38:08.640 に答える
7

System.exit() を呼び出すか、シグナルを介して終了すると、既存のすべてのスレッドが停止し、すべてのシャットダウン フックが開始されます。つまり、フックを開始するまでにすべてのスレッドが死んでいる可能性があります。

スレッドをきれいに停止しようとする代わりに、リソースがきれいに閉じられていることを確認する必要があります。

于 2012-09-13T11:00:34.830 に答える
5

コードをExecutorServiceにシフトできると思います

private final ExecutorService pool;
pool = Executors.newFixedThreadPool(poolSize);
pool.execute(Instance of Runnable);
pool.shutdown(); 

ExecutorService.shutdown

以前に送信されたタスクが実行される順序どおりのシャットダウンを開始しますが、新しいタスクは受け入れられません。すでにシャットダウンされている場合、呼び出しによる追加の効果はありません。

于 2012-09-13T11:31:31.367 に答える
2

スレッドをデーモン スレッドとして作成してみてください。

コンストラクターを追加する

public MyWorker(boolean isDaemon) {
this.setDaemon(true);
}

または、start を呼び出す前にデーモンに設定します。

worker1.setDaemon(true);
worker1.start();

Ctrl C を押して終了すると、スレッドは停止します。

于 2012-09-13T11:00:42.880 に答える
0

ここで起こっていることは、stopThread()メソッドを呼び出すことですが、終了する前にスレッドが実際に終了するのを待ちません。

join()JVM を停止する前にすべてのスレッドでを呼び出すと、おそらく「停止ログ」が表示されます。

public static void stopThreads() {
     worker1.stopThread();
     // .. stop other threads

    for(Thread t: workers) {
       t.join();
    }
 }
于 2012-09-13T11:26:48.840 に答える