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

时间:2014-08-27 19:17:48

标签: java multithreading interrupt shutdown-hook interrupted-exception

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

2 个答案:

答案 0 :(得分:1)

注意Runtime#addShutdownHook(Thread)的javadoc。

  

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

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

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

这个javadoc说明了shutdown钩子对这些条件的行为。

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

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

答案 1 :(得分:0)

我认为问题在于你的关机钩子是不完整的。钩子需要等到“SAFELY SHUTTING DOWN”动作完成才返回。

以下是您的代码的修改版本。

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