2009-09-23 51 views
4

在我的Swing应用程序中,我有第一次创建Swing窗体的新实例时需要几百毫秒的问题。这不是很长,但是变慢的主观印象确实令人讨厌。如何减少Java Swing窗体的感知加载时间?

它发生在所有形式,甚至JOptionPane消息或其他琐碎的形式。 (当然更大的表单需要更长的时间,因为更复杂的构造函数)

现在我注意到第二次创建一个新的表单实例是显着更快

由于最初的启动时间并不重要,我打算在启动时创建所有重要表单的不可见实例,但对我来说这看起来很脏。 (我不知道它甚至会工作)

我的问题:

  • 有没有更优雅的方式来加快表单的创建和显示?
  • 第一次显示表单时发生了什么,第二次没有发生?

回答

6

由于您描述了JOptionPane发生的问题,它听起来像类加载缓慢。你有没有机会通过网络加载?它也可能是垃圾收集,因为较旧的窗户被用来为新的窗户腾出空间。

我从垃圾收集开始,因为它很容易测试和纠正:启动Java时必须使用-verbose:gc参数(必须从控制台执行此操作),并注意GC在这些暂停期间是否正在运行。如果是,则使用-Xmx增加内存分配,并可能调整here所述的堆段。

如果这是一个网络连接速度较慢的情况(并且strays可以帮助诊断此问题),那么您需要预加载类(而不是实例化它们)。你可以在后台线程上使用Class.forName()

除了这两件显而易见的事情之外,您需要运行一个分析器来了解发生了什么。

+0

是的,你对垃圾收集是正确的。我将最小堆大小设置为100 MB,并且(主观)速度提升非常惊人。 –

4

有关性能提示,请参阅this article。从本质上讲,您希望保持最低限度的UI线程完成的工作,因为这会影响组件的渲染并使其感觉缓慢。

Swing应用程序有三种类型的线程:

  • 初始螺纹
  • UI事件调度线程(EDT)
  • 工作线程

每个应用程序都必须有一个代表其出发点的主要方法。此方法在初始或启动线程上运行。初始线程可能会读取程序参数并启动一些其他对象,但在许多Swing应用程序中,此线程的主要用途是启动应用程序的图形用户界面(GUI)。一旦大多数事件驱动的桌面应用程序启动GUI,初始线程的工作就完成了。

Swing应用程序只有一个用于UI的EDT。此线程绘制GUI组件,更新它们,并通过调用应用程序的事件处理程序来响应用户交互。所有事件处理程序都在EDT上运行,并且您只能在EDT上以编程方式与您的UI组件及其基本数据模型进行交互。在EDT上运行的任何任务都应该快速完成,以便您的用户界面能够响应用户输入。从其他线程访问您的UI组件或其事件处理程序将导致UI中的更新和绘图错误。在EDT上执行长时间运行的任务将导致应用程序无响应,因为GUI事件会累积在事件分派队列中。基于注释

更新,这里有一些其他的事情来检查:

你有一个病毒扫描程序运行?在我的工作机器上,病毒扫描程序检查所有加载的jar文件的内容,这对启动时间有巨大的影响。如果可能,请尝试关闭病毒扫描程序或禁用该文件夹。

您是否在启动时加载额外的类?理想情况下,您应该加载轻量级代理,只在第一次调用时加载实现(这是sWT中的常见做法,其中每个菜单项与轻量级委托关联,以轻松实例化在需要时执行实际处理的类型)。您可以尝试对应用程序进行分析以查看启动时创建的内容,并相应地添加一些间接方向。

+0

是的,所有这些都是非常好的建议,我在应用程序中虔诚地遵循它,但在这种情况下,我想要做的唯一工作就是显示一个表单。如果我将一部分表单创建放在一个线程中,我认为我不会获得某些东西,除了可能有很多线程问题。 –

+0

我已经用更多选项更新了我的答案 –

+0

+1谢谢,我会检查一下。 –

相关问题