在Swing应用程序中,应从哪个线程调用System.exit()?

8
在Swing应用程序中,从任何线程(例如在EDT上)调用System.exit()是否可以?
7个回答

6

如果可以避免,您不应该调用System.exit()

退出Java进程的最佳方法是让所有线程正常退出。这将终止VM。

在您的主JFrame中,您应该使用setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE)

然后,您可以调用frame.dispose()关闭JFrame并退出EDT。


3
不应该使用EXIT_ON_CLOSE,而应该使用DISPOSE_ON_EXIT。使用EXIT_ON_CLOSE将导致正在运行的线程被强行终止,不允许它们正常退出(当用户关闭JFrame时)。 - user85421
2
我不同意。垃圾回收器需要一段时间才能完成清理工作并退出应用程序。在处理完应该关闭的内容后,调用System.exit没有任何问题。文件、套接字等在调用System.exit后会自动关闭。 - Mike

5

由于在System.exit()调用后,虚拟机将被终止,因此我认为从哪个线程进行调用并没有任何区别。


我同意。由于exit()会终止其路径中的所有内容,因此您不应该真正关心哪个线程调用它。 - f1sh

3
您可以在任何线程中调用它,但我认为这样做有点粗鲁。无论其他什么正在运行,虚拟机都将被终止。
我更喜欢dispose()或者只是关闭(使用setDefaultCloseOperation(DISPOSE_ON_CLOSE))任何显示的窗口(JFrame、JDialog等)。如果只有守护线程在运行,虚拟机将被终止。如果还有一些活着的非守护线程,则JVM不会终止,线程可以完成其工作。
这样做,我总是可以将一个程序(的部分)包含在另一个程序中,而不必担心其中一个程序会意外终止另一个程序。
只有极少数情况下,JVM 真正需要“杀死”它。

https://dev59.com/GmYr5IYBdhLWcg3w1NhY#13360489中有一个链接到确认dispose效果的文档。 - Martin Dorey

1

System.exit()并不会终止正在运行的线程,而是终止虚拟机本身。因此,无论在哪个线程中调用该方法,其结果始终相同,如果虚拟机死亡,则所有可能存在于线程中的不一致状态将立即不存在。


1

从任何线程中调用System.exit都没有任何问题。让它“正常”退出在实践中行不通,因为你会发现应用程序在退出之前会一直挂起,等待GC收集完毕。我已经编写了大量的GUI Swing应用程序,并且从中调用System.exit也没有任何问题。这也不是“粗鲁”的行为,而是Java的方式。


在这种情况下,您是否发现它花费了超过毫秒的时间来执行GC? - Martin Dorey

0

0

有关EDT线程正常终止的Swing规则。

最重要的是确保所有框架都已被处理。不幸的是,如果您使用没有父级的模态对话框,这可能并不那么简单,因为Swing将为此类对话框创建一个不可见的父框架。

在这种情况下,您必须列出所有框架(可以使用Frame.getFrames()),并明确地dispose()它们。

当然,您必须确保没有Thread处于活动状态(除了守护进程)。一些库甚至来自JDK的API会创建非守护线程,您必须自己关闭它们。

最后,最重要的是,不调用System.exit()在Java Web Start环境中无法正常工作(请查看this SO question以获取更多信息)。

因此,总之,我的建议是实际调用System.exit(),因为您并不总是知道应用程序将在哪个环境中启动。但我会补充一个重要的观点:确保有一个单一的点执行退出。从任何线程调用它都没问题。


AWT在Swing之下,但是https://docs.oracle.com/javase/6/docs/api/java/awt/doc-files/AWTThreadIssues.html#Autoshutdown有一些规则。您建议调用exit,因为您无法从Web Start中执行该操作...是否有缺少的否定词? - Martin Dorey

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接