使用 JavaFX Application.stop() 方法 over Shutdownhook

2022-09-03 18:35:19

因此,我使用 shutdownhook 进行清理,因为不能总是保证 shutdownhooks 线程执行,我是否应该将此代码推送到 JavaFX 应用程序线程(方法 stop())上,每次关闭应用程序时都会执行?代码运行它基本上只是关闭套接字(如果未关闭)和终止进程(如果未杀死)并不昂贵。

使用 Application.stop() 在 ShutdownHook 上进行清理是一种好的做法吗?

引用自文档:

此方法在应用程序应停止时调用,并提供一个方便的位置来准备应用程序退出和销毁资源。Application 类提供的此方法的实现不执行任何操作。

注意:此方法在 JavaFX 应用程序线程上调用。

此方法是否仅用于清理 UI 的资源?到目前为止,我根本看不到使用 shutdownhook over stop() 的原因。


答案 1

stop()仅当您通过退出应用程序时(或者当最后一个窗口关闭,如果为 true)时,才会调用。如果调用,或者如果运行JVM的本机进程被中断(例如,在类似*nix的操作系统上的ctrl-C),除了退出JavaFX应用程序的常用方式之外,关闭钩子将执行。Platform.exit()Platform.implicitExitSystem.exit()

请注意,在调用 之前,在主线程中注册 shutdown 挂钩似乎很重要。Application.launch()

stop()在FX应用程序线程上执行,因此访问UI元素是安全的(例如,显示“保存未保存的更改”对话框等)。关闭钩子在后台线程中运行,因此无法访问UI元素(实际上FX Toolkit可能在该阶段之前已经停止运行)。

因此,选择取决于用例。

为了使这一点更加具体,这里有一个快速测试类:

import javafx.application.Application;
import javafx.application.Platform;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.HBox;
import javafx.stage.Stage;

public class ShutdownTest extends Application {

    @Override
    public void start(Stage primaryStage) {
        Button platformExit = new Button("Platform Exit");
        platformExit.setOnAction(e -> Platform.exit());
        Button systemExit = new Button("System Exit");
        systemExit.setOnAction(e -> System.exit(0));
        Button hang = new Button("Hang");
        hang.setOnAction(e -> {while(true);});
        HBox root = new HBox(5, platformExit, systemExit, hang);
        root.setPadding(new Insets(20));
        root.setAlignment(Pos.CENTER);
        Scene scene = new Scene(root);
        primaryStage.setScene(scene);
        primaryStage.show();

    }

    @Override
    public void stop() {
        System.out.println("Stop");
    }

    public static void main(String[] args) {
        Runtime.getRuntime().addShutdownHook(new Thread(() -> System.out.println("Shutdown hook")));
        launch(args);
    }
}

我在Mac OS X上测试了这个。

通过“平台退出”按钮退出,关闭窗口,或右键单击Dock并选择“退出”将同时执行该方法和关闭挂钩。stop()

通过“系统退出”按钮退出,通过强制进程从“活动监视器”退出,或者从命令行中终止进程,将仅执行关闭挂钩。通过按“挂起”按钮,然后右键单击Dock并选择“强制退出”来挂起应用程序具有相同的结果。kill id

通过向进程(或从命令行)发送 SIGKILL 退出,既不执行该方法,也不执行关闭挂钩。kill -9 idkill -SIGKILL idstop()


答案 2

推荐