Stage.setOnCloseRequest()和Runtime.addShutdownHook()之间有什么区别?

时间:2015-12-22 13:39:33

标签: java javafx shutdown shutdown-hook

编写JavaFX应用程序时,可以使用javafx.stage.Stage方法为任何setOnCloseRequest(EventHandler<WindowEvent>)提供关闭挂钩。如果您使用主JavaFX场景执行此操作,它将用作应用程序关闭挂钩,并可用于安全地保存/释放重要的系统资源等。但如果您实现{{{},则可以实现相同(或非常类似) 1}}并使用java.lang.Thread方法将其添加为关闭挂钩。

这些方法之间有什么不同。如果我拨打Runtime.getRuntime().addShutdownHook(Thread),两者都有效吗?如果我拨打Platform.exit(),两者都有效吗?哪一个被认为是最安全的(意思是,更好地确保保存/释放系统资源)方法?除了那些我应该考虑的方法之外,还有更好的方法吗?

1 个答案:

答案 0 :(得分:1)

这些根本不同。

当用户请求关闭该特定阶段时(通常通过按下窗口中特定于操作系统的“关闭”按钮),将执行为setOnCloseRequest()的特定阶段指定的处理程序。它在FX Application Thread上调用,并在窗口实际关闭之前被调用。它的执行并不意味着应用程序正在退出,FX工具包正在关闭,或者Java虚拟机正在退出。这里的处理程序可能不仅假设FX工具包仍在运行,而且可以修改UI(因为它在FX应用程序线程上)并且可以通过使用事件来否决关闭窗口的请求。

关闭挂钩是用户提供的线程,在Java虚拟机退出时执行。它是自己的线程,并作为关闭序列的一部分执行。因此,它不能假设任何其他服务正在运行。来自API docs

  

他们也不应盲目依赖可能的服务   注册了他们自己的关闭钩子,因此可能自己   关闭的过程。尝试使用其他基于线程的   例如,AWT事件派遣线程等服务可能会导致   死锁。

适用于AWT事件派发线程的同样警告也适用于FX应用程序线程。

在某些非常特殊的情况下,调用setOnCloseRequested处理程序可能表明JVM可能很快就要退出。这些情况包括以下所有情况,但我可能省略了一些内容:

  1. 处理程序不使用事件
  2. 舞台是最后一个开放的舞台
  3. Platform.isImplicitExit()返回true
  4. 没有非守护程序线程正在运行,并且Application实例的stop()方法
  5. 都没有启动任何非守护程序线程

    您应该使用哪种方式完全取决于您要做的事情。如果目标是释放作为JavaFX应用程序的一部分启动的资源,这些资源在应用程序退出时不再需要,我不会使用其中任何一个,但会覆盖Application.stop() method