Platform.exit() has no effect within infinite loop in JavaFX

Cyber_Agent :

EDIT: I had originally believed this problem to have been caused by the ifPresentOrElse statement, however I now understand this is not the case and the infinite while loop is to blame for this behavior, and have renamed the question (see comments and chosen answer).

There is an existing question here that shares a similar behavior with this question, however I believe that the solutions are different enough for this not to be considered a duplicate.

Original Question:

Suppose I have a JavaFX application whose start method (in the Application thread) contains the following code:

while(true) {
        new TextInputDialog().showAndWait()
       .ifPresentOrElse(System.out::println, 
                        Platform::exit);
}

The behavior of this should be that, if the OK button of the TextInputDialog is pressed (making a result present), the text entered within the dialog should be printed. If the CANCEL button is pressed, the Platform::exit statement will be called and the JavaFX application will exit.

The former case works as expected, however the latter doesn't. If the CANCEL button is pressed, the application stays alive and the dialog is opened again as if the OK button had been pressed, however no text is printed, which means that the Platform::exit statement must have been reached instead of the System.out::println statement. In an attempt to debug this issue, I adjusted the original code to the following:

while(true) {
    new TextInputDialog().showAndWait()
   .ifPresentOrElse(System.out::println, 
                   () -> System.out.println("The latter statement has been reached"));
}

When running this code and pressing the CANCEL button, "The latter statement has been reached" is printed to the screen, proving that the Platform::exit was being reached in the original code, but was not closing the application as expected.

Interestingly enough, if I edit the original code once more to the following:

while(true) {
    new TextInputDialog().showAndWait()
   .ifPresentOrElse(System.out::println, 
                    () -> System.exit(0));
}

...the program exits as expected.

I have never encountered a behavior like this before, and I am truly at a loss as to what is going on. Any insight would be greatly appreciated.

Andreas :

Read the documentation of Platform.exit():

Causes the JavaFX application to terminate. If this method is called after the Application start method is called, then the JavaFX launcher will call the Application stop method and terminate the JavaFX application thread. The launcher thread will then shutdown. If there are no other non-daemon threads that are running, the Java VM will exit. If this method is called from the Preloader or the Application init method, then the Application stop method may not be called.

This method may be called from any thread.

As can be seen, calling the method will not kill threads, so the thread running your while(true) loop will continue to run, and will prevent the program from ending.

You need to change the code so the while loop ends too, e.g. something like this:

AtomicBoolean keepRunning = new AtomicBoolean(true);
while (keepRunning.get()) {
    new TextInputDialog().showAndWait()
        .ifPresentOrElse(System.out::println, 
                         () -> keepRunning.set(false));
}
Platform.exit();

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=140429&siteId=1