在Shutdownhook上使用JavaFX Application.stop()方法

Tom*_*iak 9 java javafx

所以我使用shutdownhook进行清理,因为它并不总是保证shutdownhooks线程执行,我应该把这个代码推送到每次关闭我的应用程序时执行的JavaFX应用程序线程(方法stop())吗?如果没有关闭代码运行它基本上只是关闭套接字并且如果没有被杀死则杀死进程并不昂贵.

使用Application.stop()来清理ShutdownHook是一种好习惯吗?

来自doc的引用:

应用程序停止时会调用此方法,并为应用程序退出和销毁资源提供方便的位置.Application类提供的此方法的实现不执行任何操作.

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

此方法仅用于清理UI的资源吗?到目前为止,我根本没有看到使用shutdownhook over stop()的原因.

Jam*_*s_D 18

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

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);
    }
}
Run Code Online (Sandbox Code Playgroud)

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

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

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

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

  • @TomasBisciak绝大多数JavaFX应用程序都不会调用`System.exit()`(你应该总是喜欢`Platform.exit()`)而不是从命令行运行(减少中断的可能性),所以通常`stop()`就足够了.但同样,这取决于您的用例. (3认同)