java线程在OS启动关闭期间停止(与java文档相矛盾!)

java线程在OS启动关闭期间停止(与java文档相矛盾!),java,multithreading,interrupt,shutdown-hook,interrupted-exception,Java,Multithreading,Interrupt,Shutdown Hook,Interrupted Exception,java.lang.Thread.setDaemon(布尔值) 当运行的线程都是守护进程线程时,Java虚拟机将退出 然而,在下面的代码中,“安全关闭”在中断(操作系统风格)进程时从未发生 不,我没有用西格基尔 既然文档是错误的(?),我唯一的办法是跟踪所有非守护进程线程并在关闭钩子中加入它们吗 public class Main { public static void main(String... args) { Runtime.getRuntime().addShutdownH

java.lang.Thread.setDaemon(布尔值)

当运行的线程都是守护进程线程时,Java虚拟机将退出

然而,在下面的代码中,“安全关闭”在中断(操作系统风格)进程时从未发生 不,我没有用西格基尔

既然文档是错误的(?),我唯一的办法是跟踪所有非守护进程线程并在关闭钩子中加入它们吗

public class Main {
  public static void main(String... args) {
    Runtime.getRuntime().addShutdownHook(new Thread() {
      public void run() {
        System.out.println("shutdown hook activated");
      }
    });
    new Thread(new Runnable() {
      public void run() {
        while (true) {
          try {
            System.out.println("sleeping for 1000 seconds!");
            Thread.sleep(1000000);
          } catch (InterruptedException e) {
            System.out.println("INTERRUPTED");
            break;
          }
        }
        System.out.println("SAFELY SHUTTING DOWN");
      }
    }).start();
  }
}

注意
运行时#addShutdownHook(线程)
的javadoc

Java虚拟机会关闭,以响应两种 活动:

  • 程序正常退出,当最后一个非守护进程线程退出时,或者当调用exit(相当于System.exit)方法时,或者
  • 当用户中断(如键入
    ^C
    )或系统范围内的事件(如用户注销或退出)时,虚拟机被终止 系统关闭
SIGINT是一种用户中断,相当于命令行上的
^C

这个javadoc说明了在这些条件下关闭钩子的行为

您引用的javadoc解释了JVM在守护进程线程上下文中的行为


它们不是相互排斥的。此外,没有任何迹象表明您正在运行的线程将被中断。

我认为问题在于您的关闭挂钩不完整。钩子需要等待“安全关闭”操作完成后才能返回

下面是代码的修改版本,可以正常工作

public static void main(String... args)  {

    final AtomicBoolean shouldBeRunning = new AtomicBoolean(true);
    final AtomicBoolean isRunning = new AtomicBoolean(false);

    Runtime.getRuntime().addShutdownHook(new Thread() {
        public void run() {
            shouldBeRunning.set(false);
            System.out.println("shutdown hook activated");
            while(isRunning.get()) {
                try {
                    System.out.println("waiting on safe shutdown to complete");
                    Thread.sleep(250);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    });
    new Thread(new Runnable() {
        public void run() {
            isRunning.set(true);
            while (shouldBeRunning.get()) {
                try {
                    System.out.println("sleeping for 1 seconds!");
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    System.out.println("INTERRUPTED");
                    break;
                }
            }
            System.out.println("SAFELY SHUTTING DOWN");
            isRunning.set(false);
        }
    }).start();
}

public static void main(String... args) throws InterruptedException {

    final AtomicBoolean shouldBeRunning = new AtomicBoolean(true);
    final AtomicBoolean isRunning = new AtomicBoolean(false);

    Runtime.getRuntime().addShutdownHook(new Thread() {
        public void run() {
            shouldBeRunning.set(false);
            System.out.println("shutdown hook activated");
            while(isRunning.get()) {
                try {
                    System.out.println("waiting on safe shutdown to complete");
                    Thread.sleep(250);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    });
    new Thread(new Runnable() {
        public void run() {
            isRunning.set(true);
            while (shouldBeRunning.get()) {
                try {
                    System.out.println("sleeping for 1 second!");
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    System.out.println("INTERRUPTED");
                    break;
                }
            }
            System.out.println("SAFELY SHUTTING DOWN");
            isRunning.set(false);
        }
    }).start();
}
输出为:

sleeping for 1 second!
sleeping for 1 second!
shutdown hook activated
waiting on safe shutdown to complete
waiting on safe shutdown to complete
SAFELY SHUTTING DOWN

跟踪所有非守护进程线程并在关闭挂钩中加入它们将不允许您阻止程序终止,因为关闭挂钩有时间限制。当这个时间到期时,JVM将退出,即使钩子尚未完成。

文档没有错。从逻辑上讲,“Java虚拟机在运行的线程都是守护进程线程时退出”并不意味着它在其他情况下也不会关闭。文档已经解释了它的含义,因此您的示例与文档并不矛盾。“一旦关闭序列开始,它就只能通过调用halt方法来停止,而halt方法会强制终止虚拟机。”shutdown hook文档非常清楚,您不能使用它来停止关闭(如果您阅读文档的其余部分,您将看到漏洞,但它非常脆弱)同时提到了
SIGINT
突然终止
。您也知道关机挂钩可能永远不会被称为对吗?@user3338098您没有得到“与文档所说相反的结果”。“正如我所说的,您引用的文档没有说明或暗示您试图解决的问题。你的解释不合逻辑。具体来说,你是在否认前因。