EDIT
:我最初认为这个问题是由ifPresentOrElse
语句引起的,但是我现在明白情况并非如此,无限while循环是这种行为的罪魁祸首,并重命名了这个问题(请参阅评论和所选答案)。
这里有一个与这个问题有相似行为的现有问题,但是我相信解决方案足够不同,不会被视为重复。
原始问题:
假设我有一个 JavaFX 应用程序,其启动方法(在应用程序线程中)包含以下代码:
while(true) {
new TextInputDialog().showAndWait()
.ifPresentOrElse(System.out::println,
Platform::exit);
}
这样做的行为应该是,如果按下TextInputDialog的"确定"按钮(使结果出现),则应打印在对话框中输入的文本。如果按下CANCEL按钮,将调用Platform::exit
语句,并且 JavaFX 应用程序将退出。
前一种情况按预期工作,但后一种情况则不然。如果按下CANCEL按钮,应用程序将保持活动状态,并且对话框将再次打开,就像按下了"确定">按钮一样,但是不会打印任何文本,这意味着必须已到达Platform::exit
语句而不是System.out::println
语句。为了调试此问题,我将原始代码调整为以下内容:
while(true) {
new TextInputDialog().showAndWait()
.ifPresentOrElse(System.out::println,
() -> System.out.println("The latter statement has been reached"));
}
运行此代码并按CANCEL按钮时,"已到达后一条语句">将打印到屏幕上,证明在原始代码中已到达Platform::exit
,但未按预期关闭应用程序。
有趣的是,如果我再次将原始代码编辑为以下内容:
while(true) {
new TextInputDialog().showAndWait()
.ifPresentOrElse(System.out::println,
() -> System.exit(0));
}
。程序按预期退出。
我以前从未遇到过这样的行为,我真的不知道发生了什么。任何见解将不胜感激。
阅读Platform.exit()
的文档:
导致 JavaFX 应用程序终止。如果在调用应用程序启动方法之后调用此方法,那么 JavaFX 启动器将调用应用程序停止方法并终止 JavaFX 应用程序线程。然后启动器线程将关闭。如果没有其他非守护程序线程正在运行,Java VM 将退出。如果从预加载器或应用程序初始化方法调用此方法,则可能不会调用应用程序停止方法。
可以从任何线程调用此方法。
可以看出,调用该方法不会杀死线程,因此运行while(true)
循环的线程将继续运行,并将阻止程序结束。
您需要更改代码,以便while
循环也结束,例如:
AtomicBoolean keepRunning = new AtomicBoolean(true);
while (keepRunning.get()) {
new TextInputDialog().showAndWait()
.ifPresentOrElse(System.out::println,
() -> keepRunning.set(false));
}
Platform.exit();