gpt4 book ai didi

java - 一起使用 Platform.exit() 和 System.exit(int)

转载 作者:塔克拉玛干 更新时间:2023-11-03 03:36:41 29 4
gpt4 key购买 nike

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

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

例如这里: Stop threads before close my JavaFX program
或此处:JavaFX application still running after close

这两个方法一个接一个执行,看起来我们在尝试复制一些 Action 。我假设,如果 Platform.exit() 成功,它不应该返回到调用 System.exit(0) 的地方。但是,如果 Platform.exit() 仅触发在另一个线程上运行的一些关闭操作,返回并且可以调用 System.exit(0) 那么这可能会导致一些竞争条件,两个线程试图关闭同一个应用程序。

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

最佳答案

调用 System.exit(...) 终止 Java 虚拟机。

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

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

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

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

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

下面的例子应该证明这一点:

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");
}
}

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

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(...) 返回一个值>,以下方法应该有效。请注意,这并不是真正推荐的做法:在生产代码中,您根本不应该真正依赖支持进程退出代码的平台。

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);
}
}

关于java - 一起使用 Platform.exit() 和 System.exit(int),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46053974/

29 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com