优雅地关闭Java命令行程序的最佳方法

我对优雅地关闭Java命令行程序的不同方法感兴趣。 发送终止信号不是一种选择。

我可以想到几种不同的方法。

  1. 打开端口并等待连接。 制作一个,优雅地关闭。
  2. 观察要创建的文件,然后关闭。
  3. 从终端读取一些输入,例如“执行关闭”。

第三个是不理想的,因为通常将程序输出泵送到屏幕。 第一个需要付出太多努力(我很懒)。 大多数程序员使用第二种选择吗? 如果没有,还有什么可能/优雅/简单?

你可以尝试这样的事情:

Runtime.getRuntime().addShutdownHook(new Thread() { public void run() { /* my shutdown code here */ } }); 

编辑:

关闭钩子不会执行应用程序的关闭。 相反,它为开发人员提供了一种方法来执行他/她在关机时所希望的任何清理。

来自JavaDoc for Runtime (如果您计划使用此方法,请阅读以下内容):

关闭钩子只是一个初始化但未启动的线程。 当虚拟机开始其关闭序列时,它将以某种未指定的顺序启动所有已注册的关闭挂钩,并让它们同时运行。 当所有钩子都完成后,如果启用了终止退出,它将运行所有未被发送的终结器。 最后,虚拟机将停止。 …

你可以尝试使用Runtime.getRuntime().addShutdownHook()来满足你的要求。 通过这种方式,您可以注册一个钩子来执行清理,以便执行正常关闭。

编辑

http://java.sun.com/j2se/1.4.2/docs/api/java/lang/Runtime.html#addShutdownHook(java.lang.Thread)public void addShutdownHook(Thread hook)注册新的虚拟机关闭钩。 Java虚拟机关闭以响应两种事件:

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

第二个选项 – 检查文件 – 超过第一个 – 监听端口 – 的好处是你有一些安全可能性。

您可以在创建文件的目录上设置权限,以便只有适当的用户才能关闭该程序。 如果您在端口上侦听任何用户都可以连接到它。

如果你想使用套接字版本,它实现起来非常简单。 这是代码:

 ServerSocket server = new ServerSocket(8080); System.out.println("Socket listening!"); server.accept(); System.out.println("Connection received!"); 

您可以轻松地将此代码嵌入到您从程序开始的单独线程中,然后让它修改全局状态以启动关闭。

前两个选项很容易实现。 你也可以使用一些JMX的东西(我不太了解)。 Tomcat使用第一种方法,我在我的两个项目中应用了1和2。

考虑使用JMX组件。 然后,您可以在本地或通过网络与JConsole连接,并与您的组件进行通信。 然后组件可以正常关闭程序。

使用Java 6 u 10或更高版本,您可以使用JVisualVM执行相同操作。

我建议使用关机钩子。 它将允许您的程序使用标准OS工具进行控制。 它也不需要任何额外的访问外部资源(磁盘,端口等)。