Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/320.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java JVM如何终止守护进程线程?或者如何编写优雅终止的守护进程线程_Java_Multithreading_Jvm_Daemon - Fatal编程技术网

Java JVM如何终止守护进程线程?或者如何编写优雅终止的守护进程线程

Java JVM如何终止守护进程线程?或者如何编写优雅终止的守护进程线程,java,multithreading,jvm,daemon,Java,Multithreading,Jvm,Daemon,假设情景: 我有一个守护进程线程负责一些I/O,主线程完成并返回,JVM决定终止我的守护进程线程 它是如何做到这一点的?打断最终确定?如何对守护进程线程进行编码,使其在终止时能够正常反应?我刚刚编写了以下代码作为测试: public class DaemonThreadPlay { public static void main(String [] args) { Thread daemonThread = new Thread() { publi

假设情景:
我有一个守护进程线程负责一些I/O,主线程完成并返回,JVM决定终止我的守护进程线程


它是如何做到这一点的?打断最终确定?如何对守护进程线程进行编码,使其在终止时能够正常反应?

我刚刚编写了以下代码作为测试:

public class DaemonThreadPlay {
    public static void main(String [] args) {
        Thread daemonThread = new Thread() {
            public void run() {
                while (true) {
                    try {
                        System.out.println("Try block executed");
                        Thread.sleep(1000l);
                    } catch (Throwable t) {
                        t.printStackTrace();
                    }
                }
            }

            @Override
            public void finalize() {
                System.out.println("Finalize method called");
            }
        };
        daemonThread.setDaemon(true);
        daemonThread.start();

        try {
            Thread.sleep(2500l);
        } catch (Throwable t) {
            //NO-OP
        }
    }
}    
我将断点放在守护进程线程的catch块和finalize方法中。即使执行了try块,也未到达断点。显然,这段代码存在同步/计时问题,但我认为我们可以安全地得出结论,守护进程线程在关闭时不会中断,也不一定会调用它们的finalize()方法

您始终可以向JVM运行时添加关闭挂钩:

Thread shutdownHook = ... // construct thread that somehow
                          // knows about all the daemon threads
Runtime.getRuntime().addShutdownHook(shutdownHook);

显然,关闭钩子可以完成“正常”关闭所需的任何任务。

AFAIK,守护进程线程并不真正用于主流I/O工作。如果所有线程都已完成,JVM可能会突然关闭所有守护进程线程。针对您的需求,可能的解决方法是创建一个Executor服务,如下所示:

ExecutorService execPool = Executors.newSingleThreadExecutor(new ThreadFactory() {

    @Override    
    public Thread newThread(Runnable runnable) {       
         Thread thread = Executors.defaultThreadFactory().newThread(runnable);
         thread.setDaemon(true);
         return thread;    
    } 
}); 
从关闭挂钩调用executorservice关闭方法

Runtime.getRuntime().addShutdownHook(....)

使用中断和连接:

class Daemon extends Thread {
    public void run() {
        while (true) {
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                System.out.println(e);
                break;
            }
        }
        System.out.println("exit run()");
    }
}   
public class So8663107 {
    public static void main(String[] arguments) throws InterruptedException {
        System.out.println(Thread.activeCount());
        Daemon daemon = new Daemon();
        daemon.setDaemon(true);
        daemon.start();
        Thread.sleep(2500);
        System.out.println(Thread.activeCount());
        daemon.interrupt();
        daemon.join();
        System.out.println(Thread.activeCount());
    }
}

我想你误解了什么是守护线程

总之,它基本上意味着守护进程线程不应该执行任何I/O或持有任何资源。如果您违反了这个基本规则,那么您的线程就没有资格成为守护进程线程

添加关机挂钩是确保在JVM终止之前调用代码的标准方法,但即使这样也不能100%保证—例如,JVM可能会崩溃,让操作系统以保护操作系统的方式整理资源,但很可能会使应用程序处于不一致/错误的状态


系统检查点和恢复机制可以追溯到软件的早期(例如操作系统和批处理操作),不幸的是,由于没有“银弹”方法(API),这个轮子不断被重新发明它以一种非常通用的方式解决了这个问题。

我喜欢关机挂钩。在寻找获取活动线程的方法时可以找到它。必须遍历数组以检查至少一个用户线程
我认为关机挂钩是最好的解决方案,以前从未了解过此功能。我想我将在我的主类中保留对我的关闭钩子的引用,并在关闭钩子中保留我的守护进程线程的集合。那我就可以打断他们了。一旦实现了我的代码,我将尝试发布它。如果显式调用
System.gc()
,并且未设置JVM选项
-XX:+DisableExplicitGC
,则守护进程线程将退出。这意味着垃圾收集器负责在所有用户线程完成后关闭守护进程线程。您可以做的另一件事是引入finally块,无论try-catch块内发生什么,都保证调用它!通过这种方式,您可以关闭守护进程线程打开的任何资源,并在其中实现任何优雅的终止@熟练工人3小心不要草率下结论。当JVM在可视化调试期间停止时,很可能根本不会命中断点,因为JVM已经与调试器断开连接(我用IntelliJ IDEA目睹了这种行为)。我认为您不理解这个问题。我不想中断我的守护进程线程。我想知道JVM是如何终止它们的,以及如何处理它们。对不起,我试图回答:“我如何对我的守护进程线程进行编码,使其能够优雅地终止?”你看了源代码了吗?@StephenC,我没有想到这一点,肯定会给出一个明确的答案(尽管不一定是有用的答案)。然而,我个人并没有足够的勇气去尝试,也不指望其他人去尝试。好吧,让我更明确一点。回答这样一个问题的最好方法是查看源代码,或者至少是Java代码。总的来说,它很容易阅读和评论。(我不明白一个问题的确定答案如何不如一个非确定答案有用……特别是如果你是阅读代码的人!)告诉OP看源代码不是答案。这显示了特定的实现,而不是API要求。文档有它的位置。守护进程线程不应该执行IO或保存资源的说法的依据是什么?遵循提供的链接,您将获得一些见解。对不起,我不同意。只要理解一个守护进程线程可以在处理过程中被杀死,就不会有危险,除非你知道一些关于java资源泄漏的事情,我不知道。如果守护进程线程拥有数百个资源,终止JVM是疯狂的,更糟糕的是,当它处于一系列关键的写操作的中间时,就会发生关闭。你实际上是在冒应用程序一致性的风险。您也不同意Brian Goetz的观点,他写了“Java并发性在实践中”。。。不同意是可以的,但是我认为在少数情况下你可能是对的。你的newThread方法确实每次都会创建一个新的线程工厂。调用
Executors.defaultThreadFactory()
只会返回一个
新的defaultThreadFactory()