System.exit()
是否可以?如果可以避免,您不应该调用System.exit()
。
退出Java进程的最佳方法是让所有线程正常退出。这将终止VM。
在您的主JFrame
中,您应该使用setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE)
。
然后,您可以调用frame.dispose()
关闭JFrame
并退出EDT。
由于在System.exit()
调用后,虚拟机将被终止,因此我认为从哪个线程进行调用并没有任何区别。
dispose()
或者只是关闭(使用setDefaultCloseOperation(DISPOSE_ON_CLOSE)
)任何显示的窗口(JFrame、JDialog等)。如果只有守护线程在运行,虚拟机将被终止。如果还有一些活着的非守护线程,则JVM不会终止,线程可以完成其工作。System.exit()
并不会终止正在运行的线程,而是终止虚拟机本身。因此,无论在哪个线程中调用该方法,其结果始终相同,如果虚拟机死亡,则所有可能存在于线程中的不一致状态将立即不存在。
从任何线程中调用System.exit都没有任何问题。让它“正常”退出在实践中行不通,因为你会发现应用程序在退出之前会一直挂起,等待GC收集完毕。我已经编写了大量的GUI Swing应用程序,并且从中调用System.exit也没有任何问题。这也不是“粗鲁”的行为,而是Java的方式。
从任何线程中调用System.exit是安全的,但不能从关闭挂钩线程中调用。我最近不得不调试这样的流程https://knotgillcup.blogspot.com/2019/08/systemexit-not-working.html
终止JVM的更加暴力的方法是调用Runtime.halt()方法。
有关EDT线程正常终止的Swing规则。
最重要的是确保所有框架都已被处理。不幸的是,如果您使用没有父级的模态对话框,这可能并不那么简单,因为Swing将为此类对话框创建一个不可见的父框架。
在这种情况下,您必须列出所有框架(可以使用Frame.getFrames()
),并明确地dispose()
它们。
当然,您必须确保没有Thread
处于活动状态(除了守护进程)。一些库甚至来自JDK的API会创建非守护线程,您必须自己关闭它们。
最后,最重要的是,不调用System.exit()在Java Web Start环境中无法正常工作(请查看this SO question以获取更多信息)。
因此,总之,我的建议是实际调用System.exit()
,因为您并不总是知道应用程序将在哪个环境中启动。但我会补充一个重要的观点:确保有一个单一的点执行退出。从任何线程调用它都没问题。
EXIT_ON_CLOSE
,而应该使用DISPOSE_ON_EXIT
。使用EXIT_ON_CLOSE
将导致正在运行的线程被强行终止,不允许它们正常退出(当用户关闭JFrame时)。 - user85421