Java 如何以安全的方式关闭软件?

Java 如何以安全的方式关闭软件?,java,api,exit,termination,Java,Api,Exit,Termination,到目前为止,我使用我的应用程序作为一个独立的产品。所以,当用户按下“停止”按钮时,我调用了System.exit(0)很好 现在,我的应用程序将从另一个程序(以编程方式)调用。因此,System.exit(0)不仅会杀死我的进程,还会杀死启动我程序的外部软件 那么,如果收到来自外部软件的相应请求,关闭应用程序的正确方法是什么?我的应用程序是一个GUI应用程序。所以,我想关闭窗口,但我也想关闭我的程序执行的所有进程 添加: 更具体地说,我想关闭程序启动的所有线程。我的程序不会启动任何操作系统进程或

到目前为止,我使用我的应用程序作为一个独立的产品。所以,当用户按下“停止”按钮时,我调用了
System.exit(0)很好

现在,我的应用程序将从另一个程序(以编程方式)调用。因此,
System.exit(0)
不仅会杀死我的进程,还会杀死启动我程序的外部软件

那么,如果收到来自外部软件的相应请求,关闭应用程序的正确方法是什么?我的应用程序是一个GUI应用程序。所以,我想关闭窗口,但我也想关闭我的程序执行的所有进程

添加:


更具体地说,我想关闭程序启动的所有线程。我的程序不会启动任何操作系统进程或任何其他程序。

只要您的程序没有与其他程序共享应用程序服务器,请通过调用
系统关闭VM。退出(0)
终止所有线程

从 System.exit终止当前运行的Java虚拟机)

编辑:
如果要在关机前执行一些清理代码,

如果已启动的线程仍在处理,则调用System.exit(0)将导致它们被终止。在某些情况下,这会使应用程序处于不一致的状态。例如,假设线程正在保存一个文件

在调用System.exit之前,您应该确保您的线程都“高兴”地死去

对于长时间运行的线程,可以使用的一种技术是中毒。为此,您向线程发送一条消息,它们现在应该优雅地死去,即poson消息。一旦它们都死掉了,就可以安全地调用System.exit(0)来终止Swing事件处理线程

有很多不同的方法实现中毒,您可以设置一个全局标志变量,让线程检查它们是否中毒,或者您可以使用Java5线程库。以这个Javadoc为例,您会发现对该技术的引用:

不幸的是,“一刀切”的答案是System.exit的替代品减少了

通常需要设置某种标志,向所有线程发出退出时间的信号,并确保它们定期检查该标志。这将使它们在不突然停止的情况下优雅地清理,并确保效果仅限于您自己的组件。在这种情况下,应用程序的主线程也将观察该标志,等待所有“worker”类型的线程完成,然后返回堆栈,直到到达应用程序的入口点

这个问题与不推荐的
Thread.stop
(etc)方法没有太大区别,特别是在用更尊重的方法替换System.exit时。因此,这本书可能是有用的读物


抛出一个异常(一个称为类似
ApplicationStopException
的自定义异常)来释放主线程的堆栈并不是一个坏主意;这可以避免您必须处理代码中的所有特殊逻辑,而是让“消息”传播到更高的级别,在那里,他们可以采取任何必要的操作来优雅地退出程序。

我建议您进行标记以停止线程,以便线程知道何时必须停止。对于GUI和Windows,可以调用frame.dispose()


对于System.exit(),我认为它不会影响调用者,您可以尝试看看真正的效果,但正如其他人已经建议的那样,不要直接这样调用它,只让线程自行停止

@Roman:所谓“由我的程序执行的进程”,您是指Java程序正在运行的所有线程还是您的程序生成的所有线程,比如说,其他可执行文件(Un*x shell进程、.exe、在其VM中运行的其他Java程序等等)?@wizardofods,我的意思是“我的Java程序正在运行的所有线程”。如何调用您的程序?它的某个方法是由一个已经运行的Java程序调用的,所以这两个程序实际上是一个程序吗?或者另一个程序正在进行系统调用,以便用您的程序启动新的Java VM?下面我给出的答案描述了如何正确终止线程,而不是进程。我希望您觉得它很有用。@stacker,您的意思是
System.exit(0)
将关闭所有线程,包括外部软件(启动我的程序)的线程。它将杀死JVM。因此,如果外部软件通过生成一个Java进程来启动您的程序,那么就可以了。如果外部软件是只创建类实例并运行它们的Java代码,那么外部代码也将被删除。