一起使用Platform.exit()和System.exit(int) [英] Using Platform.exit() and System.exit(int) together

查看:119
本文介绍了一起使用Platform.exit()和System.exit(int)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想关闭带有指定返回码的javafx应用程序。浏览SO上的答案,我发现以下成语:

I would like to close a javafx application with a specified return code. Browsing through answers on SO, I found the following idiom:

Platform.exit();
System.exit(0); 

例如:
关闭我的JavaFX程序前停止线程

或此处: JavaFX应用程序在关闭后仍在运行

这两个方法一个接一个地执行,看起来我们正在尝试复制某些操作。我认为,如果 Platform.exit()成功,它不应该返回到 System.exit(0)被调用。但是,如果 Platform.exit()仅触发在另一个线程上运行的某些结束操作,则返回 System.exit(0)可以调用然后这可能会导致一些竞争条件,其中两个线程试图关闭同一个应用程序。

These two methods executed one after another look like we are attempting to duplicate some actions. I would assume, that if Platform.exit() is successful, it should not return to the place where System.exit(0) is called. If however Platform.exit() only triggers some closing action running on another thread, returns and System.exit(0) can be called then this may cause some race condition, where two threads are trying to close the same application.

那么,这个成语究竟是如何运作的?

So, how does this idiom exactly work?

推荐答案

致电 System.exit(...)终止Java虚拟机。

Calling System.exit(...) terminates the Java Virtual Machine.

据我所知,调用 Platform.exit()只是表示JavaFX Toolkit已关闭,导致在FX Application线程上调用应用程序实例的 stop()方法,并允许FX应用程序线程终止。这反过来导致 Application.launch()返回。如果你在 main(...)方法中使用通常的习语:

As I understand it, calling Platform.exit() just signals the JavaFX Toolkit to shut down, resulting in the application instance's stop() method being called on the FX Application thread, and the FX Application Thread being allowed to terminate. This in turn causes Application.launch() to return. If you are using the usual idiom in your main(...) method:

public static void main(String[] args) {
    Application.launch(args);
}

然后一次 launch()返回, main()方法没有任何内容可做,并且没有(只要没有运行非守护程序线程)应用程序以正常方式退出办法。 在任何情况下,Platform.exit()都不会创建对 System.exit(...)的调用:但是在某些情况下,它将允许JVM退出,因为它没有任何东西可以做。

then once launch() returns, there is nothing left for the main() method to do, and no (as long as no non-daemon threads are running) the application exits in a normal way. Platform.exit() does not create a call to System.exit(...) under any circumstances: however under certain circumstances it will allow the JVM to exit simply because there is nothing left for it to do.

如果你调用 System.exit(。 ..) JVM基本上会立即退出。因此,例如,如果您在 Application.launch()之后的 main(...)方法中有代码,该代码在调用 Platform.exit()后执行,但在调用 System.exit(...)后不执行。同样,如果覆盖 Application.stop(),则在调用<$后调用 stop()方法c $ c> Platform.exit(),但在调用 System.exit(...)之后却没有。

If you call System.exit(...) the JVM basically exits immediately. So, for example, if you have code in the main(...) method after Application.launch(), that code gets executed after a call to Platform.exit(), but not after a call to System.exit(...). Similarly, if you override Application.stop(), the stop() method is called after a call to Platform.exit(), but not after a call to System.exit(...).

如果您运行非守护程序线程, Platform.exit()将不会强行关闭它们,但是 System.exit()将。

If you have non-daemon threads running, Platform.exit() will not forcibly shut them down, but System.exit() will.

以下示例应证明:

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

public class ExitTest extends Application {

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

    @Override
    public void start(Stage primaryStage) {
        Button startThread = new Button("Start non-daemon thread");
        startThread.setOnAction(e -> new Thread(() -> {
            System.out.println("Starting thread");
            try {
                Object lock = new Object();
                synchronized(lock) {
                    lock.wait();
                }
            } catch (InterruptedException exc) {
                System.err.println("Interrupted");
                Thread.currentThread().interrupt();
            } finally {
                System.out.println("Thread complete");
            }
        }).start());

        Button exit = new Button("Simple Exit");
        exit.setOnAction(e -> {
            System.out.println("Calling Platform.exit()");
            Platform.exit();
        });

        Button forceExit = new Button("Force exit");
        forceExit.setOnAction(e -> {
            System.out.println("Calling Platform.exit():");
            Platform.exit();
            System.out.println("Calling System.exit(0):");
            System.exit(0);
        });

        Scene scene = new Scene(new HBox(5, startThread, exit, forceExit));
        primaryStage.setScene(scene);
        primaryStage.show();
    }

    public static void main(String[] args) {
        launch(args);
        System.out.println("launch() complete");
    }
}

通常建议您退出JavaFX应用程序调用 Platform.exit(),它允许正常关闭:例如,如果你需要任何清理代码,你可以把它放在 stop()方法和 Platform.exit()将允许它被执行。如果您正在运行必须终止的后台线程,请使它们成为守护程序线程,或者通过执行程序服务执行它们,并从 stop()方法关闭执行程序服务。以下是使用该技术的上述示例的修改。

It's generally recommended that you exit a JavaFX Application with a call to Platform.exit(), which allows for a graceful shutdown: for example if there is any "cleanup" code you need, you can put it in the stop() method and Platform.exit() will allow it to be executed. If you are running background threads which must be terminated, either make them daemon threads, or execute them via an executor service, and shut down the executor service from the stop() method. Here is a modification to the above example which uses this technique.

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

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

public class ExitTest extends Application {

    private final ExecutorService exec = Executors.newCachedThreadPool();

    @Override
    public void stop() throws InterruptedException {
        System.out.println("Stop called: try to let background threads complete...");
        exec.shutdown();
        if (exec.awaitTermination(2, TimeUnit.SECONDS)) {
            System.out.println("Background threads exited");
        } else {
            System.out.println("Background threads did not exit, trying to force termination (via interruption)");
            exec.shutdownNow();
        }       
    }

    @Override
    public void start(Stage primaryStage) {
        Button startThread = new Button("Start non-daemon thread");
        startThread.setOnAction(e -> { 
            exec.submit( () -> {
                System.out.println("Starting thread");
                try {
                    // just block indefinitely:
                    Object lock = new Object();
                    synchronized(lock) {
                        lock.wait();
                    }
                } catch (InterruptedException exc) {
                    System.out.println("Interrupted");
                    Thread.currentThread().interrupt();
                } finally {
                    System.out.println("Thread complete");
                }
            });
        });

        Button exit = new Button("Simple Exit");
        exit.setOnAction(e -> {
            System.out.println("Calling Platform.exit()");
            Platform.exit();
        });


        Scene scene = new Scene(new HBox(5, startThread, exit));
        primaryStage.setScene(scene);
        primaryStage.show();
    }

    public static void main(String[] args) {
        launch(args);
        System.out.println("launch() complete");
    }
}

如果你想使用 Platform.exit()为了正常关闭,你想从 System.exit(...)返回一个值,以下方法应该有效。请注意,这不是真正推荐的做法:在生产代码中,您根本不应该依赖支持流程退出代码的平台。

If you want to use Platform.exit() in order to have a graceful shutdown, and you want to return a value from System.exit(...), the following approach should work. Note that this is not really a recommended practice anyway: in production code you should not really rely on the platform supporting a process exit code at all.

public class App extends Application {

    private static int exitCode = 0 ;

    public static exit(int exitCode) {
        App.exitCode = exitCode ;
        Platform.exit();
    }

    @Override
    public void start(Stage primaryStage) {
        // ...

        someThing.addEventHander(someEventType, e -> App.exit(42));

        // ...
    }

    @Override
    public void stop() {
        // cleanup code...
    }

    public static void main(String[] args) {
        Application.launch(args);
        System.exit(exitCode);
    }
}

这篇关于一起使用Platform.exit()和System.exit(int)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆