8

私は、デーモン スレッドの finally ブロックが実行されないことを知っています。しかし、私の細心の注意を払った性質は、JVM で何が起こっているのかを理解しようとするため、このブロックの下のコードを呼び出すことができませんでした。

巻き戻すべきではないが、方法がわからないというコールスタックに何らかの関係があると思います。誰かがこれに光を当ててください。ありがとう。

4

3 に答える 3

11

finallyデーモンスレッドのブロックが実行されないと誰が言いますか? これは一般的には当てはまりません。

(または) ブロックの実行中に JVM がシャットダウンされた場合、ブロックの実行が保証されないということを聞いたことがあるかもしれません。その通りです (デーモン スレッドでは簡単に発生する可能性があります)。finallytrycatch

しかし、繰り返しになりますが、通常の操作中には、ブロックがデーモンスレッドで正常に実行されるのを妨げるものは何もありません。ブロックは異なる方法で処理されません。finally

シャットダウンの問題は簡単です。JVM がシャットダウンを要求されたり、強制的にシャットダウンされたりすると、それ以上ステートメントを実行できなくなる可能性があります。

たとえば、POSIX-y オペレーティング システムでは、シグナル 9 (SIGKILL)によってアプリケーションが強制終了され、クリーンアップを実行する機会がなくなります (これが、通常、シグナル 15 (SIGTERM) が優先される理由です)。この場合、OS がそれ以上ブロックを実行させないため、JVMはブロックを実行できません。finally

于 2011-07-18T12:42:02.023 に答える
2

try または catch コードの実行中に JVM が終了すると、finally ブロックが実行されない場合があります。
通常のシャットダウン - これは、デーモン以外の最後のスレッドが終了したとき、または Runtime.exit() のときに発生します。
スレッドが終了すると、JVM は実行中のスレッドのインベントリを実行し、残っているスレッドがデーモン スレッドだけの場合は、正常なシャットダウンを開始します。JVM が停止すると、残りのデーモン スレッドはすべて放棄され、最終的にブロックは実行されず、スタックは巻き戻されず、JVM はただ終了します。デーモン スレッドは慎重に使用する必要があります。クリーンアップなしでいつでも安全に放棄できる処理アクティビティはほとんどありません。特に、何らかの種類の I/O を実行する可能性のあるタスクにデーモン スレッドを使用するのは危険です。デーモン スレッドは、メモリ内キャッシュから期限切れのエントリを定期的に削除するバックグラウンド スレッドなどの「ハウスキーピング」タスク用に保存するのが最適です。

最後の非デーモン スレッドの終了例:

public class TestDaemon {
    private static Runnable runnable = new Runnable() {
        @Override
        public void run() {
            try {
                while (true) {
                    System.out.println("Is alive");
                    Thread.sleep(10);
                    // throw new RuntimeException();
                }
            } catch (Throwable t) {
                t.printStackTrace();
            } finally {
                System.out.println("This will never be executed.");
            }
        }
    };

    public static void main(String[] args) throws InterruptedException {
        Thread daemon = new Thread(runnable);
        daemon.setDaemon(true);
        daemon.start();
        Thread.sleep(100);
        // daemon.stop();
        System.out.println("Last non-daemon thread exits.");
    }
}

出力:

Is alive
Is alive
Is alive
Is alive
Is alive
Is alive
Is alive
Is alive
Is alive
Is alive
Last non-daemon thread exits.
Is alive
Is alive
Is alive
Is alive
Is alive
于 2011-09-08T07:32:17.183 に答える
2

残りの 2 つのデーモン スレッドの前に終了する 2 つの非デーモン スレッドを作成しました。

1 つの非デーモン スレッドが 20 秒間待機し、1 つのデーモン スレッドが 40 秒間待機し、1 つの非デーモン スレッドが 15 秒間スリープし、1 つのデーモン スレッドが 30 秒間スリープし、1 つのデーモン スレッドが 10 秒間スリープします。一部のデーモンスレッドの前に非デーモンスレッドを終了するという考え。

結果が示唆するように、デーモン スレッドの Runnable タスクで rest ステートメントを実行することなく、生きている非デーモン スレッドがなくなるとすぐに JVM は終了します。

public class DeamonTest {

    public static void main(String[] args) {
        spawn(40000, Action.wait, true);
        spawn(30000, Action.sleep, true);
        spawn(10000, Action.sleep, true);
        spawn(20000, Action.wait, false);
        spawn(15000, Action.sleep, false);
    }

    enum Action {
        wait, sleep
    }

    private static void spawn(final long time, final Action action,
                              boolean daemon) {
        final Thread thread = new Thread(new Runnable() {
                @Override
                public void run() {

                    Thread thread = Thread.currentThread();
                    try {
                        switch (action) {
                        case wait: {
                            synchronized (this) {

                                System.out.println(thread + " daemon="
                                                   + thread.isDaemon() + ": waiting");
                                wait(time);
                            }
                            break;
                        }
                        case sleep: {

                            System.out.println(thread + " daemon="
                                               + thread.isDaemon() + ": sleeping");
                            Thread.sleep(time);
                        }
                        }
                        System.out.println(thread + " daemon=" + thread.isDaemon()
                                           + ": exiting");
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    } finally {
                        System.out.println(thread + " daemon=" + thread.isDaemon()
                                           + ": finally exiting");
                    }
                }

            });
        thread.setDaemon(daemon);
        thread.start();
    }
}
于 2012-07-14T15:36:49.483 に答える