问题描述
最近看到一个MVC java应用,里面的main方法是这样写的:
public static void main(String[] args)
{
SwingUtilities.invokelater(new Runnable()
{
public void run()
{
View view = new View();
Model model = new Model();
Controller controller = new Controller(view,model);
controller.start();
}
});
}
这不会使所有程序(包括模型和控制器,与 Swing 完全无关)一直运行到代码在 AWT 事件调度线程而不是主线程中结束?
如果最后一个是真的,那么这对应用程序来说真的很糟糕,因为它会阻止 EDT 执行它需要的任务(例如,调度事件,因为模型可能正在计算其他任务)。正确吗?
有一个类似的 old post(不是这个的重复)可以表明上面提到的代码是一种很好的做法,所以它让我更加困惑。
解决方法
您展示的代码片段的目的是创建 Swing UI 和模型并将它们连接在一起。
没有 Swing 更新(在对用户输入做出反应方面),因为在 run()
方法结束之前不能有任何用户输入。
虽然您可以在主线程和 EDT 之间拆分这些任务(并且可能会在第一次显示 UI 之前获得几毫秒的时间),但它也会使应用程序的设计复杂化(多线程不是一个简单的话题)并且将代码库乱扔垃圾invokeLater()
调用。除非有人证明这是必要的,否则我不会这样做。
恕我直言,EDT 是任何 GUI 应用程序中的主线程。对用户输入的每一次反应都从这个线程开始,UI 的每一次更新都必须在这个线程中完成。
长时间运行的任务应该在后台线程中完成 - 这通常意味着需要超过几毫秒的时间。
如果创建模型需要几秒钟怎么办?
在那种情况下,我会尝试将模型创建分为两部分:
- 创建所需的最小部分,以便可以显示 UI。这应该在 EDT 中完成(因为用户无论如何都必须等待这部分的完成 - 在显示 UI 之前,他无法与之交互)
- 在后台线程中完成剩余的、长时间运行的部分。
如果不能这样做怎么办?(即在模型完全初始化之前无法显示 UI)
在这种情况下,用户必须等待模型的完全初始化,然后才能看到和使用 UI。所以这个初始化是在 EDT 还是在主线程上运行都没有关系。因此,请使用更简单的解决方案:EDT 上的所有内容。
但是通过显示 splash screen
来提示用户您的应用程序正在启动