我有一个类似的问题。我有一些基本上是长时间运行的守护进程的 Java 程序。能够阻止它们并反弹(重新启动)它们真是太好了。
我使用了两种方法。两者都有优点和缺点。一种是设置一个信号处理程序,通过将这样的函数放在程序的某个类中(在我的程序中,它位于具有 main 方法的类中)。
import sun.misc.Signal;
import sun.misc.SignalHandler;
...
private static boolean stopNow = false;
private static boolean restartNow = false;
...
private static void handleSignals() {
try {
Signal.handle(new Signal("TERM"), new SignalHandler() {
// Signal handler method for CTRL-C and simple kill command.
public void handle(Signal signal) {
MyClass.stopNow = true;
}
});
}
catch (final IllegalArgumentException e) {
logger.warn("No SIGTERM handling in this instance.");
}
try {
Signal.handle(new Signal("INT"), new SignalHandler() {
// Signal handler method for kill -INT command
public void handle(Signal signal) {
MyClass.stopNow = true;
}
});
}
catch (final IllegalArgumentException e) {
logger.debug("No SIGINT handling in this instance.");
}
try {
Signal.handle(new Signal("HUP"), new SignalHandler() {
// Signal handler method for kill -HUP command
public void handle(Signal signal) {
MyClass.restartNow = true;
}
});
}
catch (final IllegalArgumentException e) {
logger.warn("No SIGHUP handling in this instance.");
}
}
这对我们的生产非常有效。您需要一个真正的 Sun JRE 才能正常工作;一个典型的 Linux 发行版附带的没有 Signal 的东西。它在 Windows 上也可以正常工作,但您没有收到 HUP 信号。你确实需要一个快捷方式或 shellscript 来启动这个东西。
另外,请记住,信号处理是一个大麻烦。不要尝试在信号处理程序中做太多事情。您可以看到我的示例代码只是设置了静态标志。我的程序的其他部分检测到标志发生了变化,然后关闭。我本可以在信号处理程序中尝试更复杂的代码,但我不想承担 QA 的负担。
另一种方法是将程序构建为 Servlet。在这种情况下,您将编写一个扩展 HttpServlet 的类。使用启动工作线程的方法覆盖 Servlet.init。同样,使用关闭自己的方法覆盖 Servlet.destroy。
然后,您可以使用像 Tomcat 这样的 Java EE 容器服务器来管理您的启动和停止。