最后在守护进程中阻塞

时间:2011-07-18 12:33:23

标签: java daemon finally

我知道最后在deamon线程中的块不会被执行。但是我一丝不苟地试图理解为什么以及JVM中发生的事情如此特殊以至于无法调用此块下的代码。

我认为它以某种方式与调用堆栈相关,它不会放松,但不知道如何。有人可以对此有所了解。 感谢。

3 个答案:

答案 0 :(得分:11)

谁说守护程序线程中的finally块不执行?这通常是

可能听说在执行finally(或{{1}期间关闭JVM时无法保证执行try块的内容阻止。这是正确的(它很容易发生在守护程序线程中)。

但同样:在正常操作期间, nothing 阻止catch块在守护程序线程中正常执行:它们以不同方式处理。

关闭问题很简单:当要求JVM关闭甚至强制关闭时,它可能根本不能再执行任何语句。

例如,在POSIX-y操作系统上,信号9(SIGKILL)强制应用程序退出,使其无法进行任何清理(这就是信号15(SIGTERM)首选的原因) ,通常)。在这种情况下,JVM 无法执行finally块,因为操作系统不会让它再运行。

答案 1 :(得分:2)

If the JVM exits while the try or catch code is being executed, then the finally block may not execute.
Normal Shutdown - this occurs either when the last non-daemon thread exits OR when Runtime.exit()
When a thread exits, the JVM performs an inventory of running threads, and if the only threads that are left are daemon threads, it initiates an orderly shutdown. When the JVM halts, any remaining daemon threads are abandoned finally blocks are not executed, stacks are not unwound the JVM just exits. Daemon threads should be used sparingly few processing activities can be safely abandoned at any time with no cleanup. In particular, it is dangerous to use daemon threads for tasks that might perform any sort of I/O. Daemon threads are best saved for "housekeeping" tasks, such as a background thread that periodically removes expired entries from an in-memory cache.

最后一个非守护程序线程退出示例:

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

答案 2 :(得分:2)

我创建了两个非守护程序线程,它们将在其余两个守护程序线程之前终止。

一个非守护程序线程等待20秒, 一个守护程序线程等待40秒, 一个非守护进程线程休眠15秒, 一个守护程序线程休眠30秒, 一个守护程序线程休眠10秒。在一些守护进程之前终止非守护进程线程的想法。

结果表明,只要没有非守护程序线程处于活动状态,JVM就会终止,而不会执行守护程序线程的Runnable任务中的其余语句,即使它们位于finally块内而不会抛出InterruptedException。 / p>

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();
    }
}