-1

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

当唯一运行的线程都是守护线程时,Java 虚拟机退出。

然而在下面的代码中,“安全关闭”在中断(操作系统风格)进程时永远不会发生,不,我没有使用 SIGKILL ......

由于文档错误(?)是我唯一的办法来跟踪所有非守护线程并在关闭挂钩中加入它们吗?

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

2 回答 2

1

请注意Runtime#addShutdownHook(Thread).

Java 虚拟机关闭以响应两种事件:

  • 程序正常退出,当最后一个非守护线程退出或调用 exit(等效于 System.exit)方法时,或
  • 虚拟机响应用户中断(例如打字^C)或系统范围的事件(例如用户注销或系统关闭)而终止。

SIGINT 是用户中断,相当于^C命令行。

此 javadoc 说明了关闭挂钩在这些条件下的行为方式。

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

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

于 2014-08-27T21:24:38.613 回答
0

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

这是您的代码的修改版本,它确实有效。

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 也会退出。

于 2014-08-27T21:32:41.837 回答