我最近看到一个MVC java应用程序,其中的主方法是这样写的:
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执行它需要的任务(例如,调度事件,因为模型可以计算其他任务)。对吗?
有一个类似的老帖子(不是这个重复的),可以建议上面提到的代码是好的实践,所以它更让我困惑。
您所展示的代码片段的目的是创建将Swing UI和模型连接在一起。
没有Swing更新(就响应用户输入而言),因为在run()
方法结束之前不能有任何用户输入。
虽然您可以在主线程和EDT之间分割这些任务(并且可能在UI第一次显示之前获得几毫秒),但它也会使应用程序的设计复杂化(多线程不是一个容易的主题)并且用invokeLater()
调用丢弃代码库。除非有人证明这是必要的,否则我不会做这件事。
IMHO的EDT是任何GUI应用程序中的主线程。每个用户输入的响应都在这个线程中开始,每个UI的更新都必须在这个线程中完成。
长时间运行的任务应该在后台线程中完成——这通常意味着任何超过几毫秒的任务。
如果创建模型需要几秒钟呢?
在这种情况下,我会尝试将模型创建分为两个部分:
- 创建显示UI所需的最小部分。这应该在EDT中完成(因为用户无论如何都必须等待这部分完成-在UI显示之前,他不能与之交互)
- 在后台线程中执行剩余的长时间运行的部分。
如果不能这样做怎么办? (即在模型完全初始化之前UI不能显示)
在这种情况下,用户必须等待模型的完全初始化才能看到并使用UI。因此,这个初始化是在EDT上运行还是在主线程上运行并不重要。因此,使用更简单的解决方案:所有内容都放在EDT上。
但是通过显示闪屏给用户提示你的应用程序正在启动