有没有办法动态重启循环打印输出的 HelloWorld Java 程序?

Is there a way to dynamically restart a HelloWorld Java program which loops print outputs?

考虑以下简单的代码,它会永远打印 "Hi world":

public class WakeMeUpSomehow {

 public static void main(String[] args) {

    while (true) {
    try {
         System.out.println( " Hi world ");
         Thread.sleep(1000);                 //1000 milliseconds is one second.
    } catch(InterruptedException ex) {
         Thread.currentThread().interrupt();
    }
    }
 }
}

这是输出:

有没有办法设计一个外部的第三个程序,它会监视这个程序以在我们杀死它时注意到它(就像在命令行中使用 CTRL+C);然后这个 "parent" 程序恢复 "Hello World" 运行 ?

我认为它可能看起来像这样:

所以我的问题是 - 我怎样才能模拟这样的代码,它具有这种 fail-safe 的能力?有没有办法做到这一点?

谢谢!

编辑:我在这里找到了一个简洁的 link,它是相关的,但解决了一些不同的问题 - How can I restart a Java application?

如果这么简单,你可以简单地使用shutdownhook。

Runtime.getRuntime().addShutdownHook(() -> {
    //do whatever you want to be done when closing the program here
});

虽然您可能会遇到一些问题,但如果您想重新启动程序并使用相同的命令行。

您可以使用关闭挂钩再次启动您的应用程序。请注意它的缺点 - 你的 JVM 永远不会停止 运行,直到你强制终止它。

http://wrapper.tanukisoftware.com/doc/english/qna-shutdown.html

首先这是一项具有挑战性的任务。试试吧,让我知道它是否有效!!!!!

public class WakeMeUpSomehow {
    static class Message extends Thread {

        public void run() {
            try {

                while(true)
                {
                System.out.println("Hello World from run");

                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    public static void main(String[] args) {
        try {
            Runtime.getRuntime().addShutdownHook(new Message());
            while(true)
            {
            System.out.println("Hello World");
            Thread.sleep(100);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

关闭挂钩保证 运行 程序的正常关闭事件,但不是所有类型的异常终止,例如 JVM 被强行终止时.

一种解决方案可能是使用批处理脚本:

@echo off
setlocal

start /wait java WakeMeUpSomehow

if errorlevel 1 goto retry
echo Finished successfully
exit

:retry
echo retrying...
start /wait java WakeMeUpSomehow

先不说你想要这样的原因 :-),"robust" 的方法是在以下位置执行你的 "parent" 程序或批处理脚本:

  1. Windows 服务执行 java 程序,详见 Install java program as a windows service: Alternative to JavaService?
  2. 3PP 调度程序
  3. 如果您使用 Linux,您可以使用 init 守护进程或 Cron 调度程序。

以上方法甚至可以承受计算机重启!

在 Windows 中,执​​行此操作的方法是 运行 您的程序作为服务。它允许在系统启动时启动程序(没有用户登录)并在程序关闭时重新启动程序。 Windows 资源工具包提供了一个名为 SrvAny.exe 的程序,它允许您 运行 任何程序即服务。

https://support.microsoft.com/en-us/kb/137890

您应该结账 monit。它提供了很多实用程序,而不仅仅是重新启动程序。

例如

  1. 它会检查您的程序是否正在消耗更多内存(可能是由于内存泄漏)。
  2. 监视文件更改。
  3. 重启程序以防崩溃。
  4. 基于脚本的自定义启动选项支持。

听起来您想 运行 您的应用程序作为 Service ( windows ) 或 Daemon (Unix).

在 Java 中,您通常为此使用服务包装器。我为此使用 Apache Commons Daemon

Commons Daemon 提供 ProcRun.exe on Windows for running your Java application as a service. You can even rename the executable to that of your program. On Unix you have JSvc 用于重新启动您的 Java 应用程序。我在主程序 class 中编写了一个精简的通用启动程序 API,这两个可执行文件都会调用它。

如果您需要在生产中执行此操作(而不是作为某种练习),我认为这是唯一可靠地执行此操作的方法。