【问题标题】:How can I close my software in a safe way?如何以安全的方式关闭我的软件?
【发布时间】:2010-04-21 15:58:43
【问题描述】:

到目前为止,我将我的应用程序用作独立产品。所以,当用户按下“停止”按钮时,我打电话给System.exit(0);,这很好。

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

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

添加:

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

【问题讨论】:

  • @Roman: by "processes executed by my program" 你是指你的 Java 程序正在运行的所有线程还是你的程序产生的所有线程,比如说,其他可执行文件(Un* x shell 进程、.exe、在其 VM 中运行的其他 Java 程序,等等)?
  • @WizardOfOdds,我的意思是“我的 Java 程序正在运行的所有线程”。
  • 你的程序是如何被调用的?它的某些方法是否被已经运行的 Java 程序调用,所以这两个有效地成为一个程序?或者其他程序是否在进行系统调用以使用您的程序启动新的 Java VM?
  • 我在下面给出的答案描述了如何正确终止线程 - 而不是进程。希望对您有所帮助。

标签: java api exit termination


【解决方案1】:

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

在调用 System.exit 之前,您应该确保您的线程都“乐意”死掉。

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

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

http://java.sun.com/j2se/1.5.0/docs/api/java/util/concurrent/BlockingQueue.html

【讨论】:

    【解决方案2】:

    只要您的程序不与其他人共享应用程序服务器,通过调用 System.exit(0) 关闭 VM 就会终止所有线程。

    来自Javadoc System.exit 终止当前运行的 Java 虚拟机)

    编辑: 如果你想在关机前做一些清理代码,http://java.sun.com/j2se/1.4.2/docs/guide/lang/hook-design.html

    【讨论】:

    • @stacker,你的意思是System.exit(0) 将关闭所有线程,包括外部软件的线程(它启动了我的程序)。
    • 它将杀死 JVM。因此,如果外部软件通过生成 Java 进程来启动您的程序,那就没问题了。如果外部软件是 Java 代码,它只是创建类的实例并运行它们,那么该外部代码也将被杀死。
    【解决方案3】:

    不幸的是,对此有“一刀切”的答案,这是 System.exit 的直接替代品。

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

    这个问题与已弃用的 Thread.stop (等)方法并没有太大的不同,尤其是在用更尊重的东西替换 System.exit 方面。鉴于此,why is Thread.stop() deprecated page 可能是有用的阅读材料。

    抛出一个异常(一个自定义的叫做ApplicationStopException之类的东西)来展开主线程的堆栈并不是一个坏主意;这可以防止您必须处理整个代码中的特殊逻辑,而是让“消息”传播到更高级别,在那里他们可以采取任何需要的操作来优雅地退出您的程序。

    【讨论】:

      【解决方案4】:

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

      对于System.exit(),我认为它不会影响调用者,你可以尝试看看真正的效果是什么,但正如其他人已经推荐的那样,不要直接调用它,让线程停下来自己

      【讨论】:

        猜你喜欢
        • 2023-03-13
        • 2014-09-14
        • 2013-01-06
        • 2010-12-15
        • 2016-07-20
        • 2022-10-14
        • 1970-01-01
        • 2013-01-03
        • 1970-01-01
        相关资源
        最近更新 更多