ddi*_*rov 8 java swing classloader
在引入Java Memory Model之后,Swing指南被更改为声明任何Swing组件需要在EDT上实例化以避免未发布的实例状态.
我无法在任何地方找到的是类加载是否也被强制要求在EDT上,还是我们可以在后台线程中预加载关键的Swing类?Sun/Oracle对此有何正式声明?是否有任何已知的类保持非线程安全静态,因此需要在EDT上加载?
澄清解决内米的问题:这是一个实际问题.我们的应用程序启动时间的相当大一部分用于在EDT上进行类加载和字体/图像加载.其中大部分可归因于Swing和相关库.
这是som背景:与许多其他Swing应用程序一样,在启动时我们预先构建了许多表单,以使UI更具响应性.在分析之后,我们发现表单构造的实际时间相对较快 - 所有类和字体的加载速度都很慢(使用按访问病毒扫描程序,监视扫描程序,审计跟踪器和上帝知道还有什么其他内容,企业设置中的磁盘读取速度很慢加上硬盘驱动程序).
我们试图在后台线程中构造相同的表单(违反Swing的规则),然后扔掉它们.一旦我们完成,我们在EDT上构建相同的表单,这比加载所有类和磁盘缓存中的任何其他文件要快得多.它适用于我们,我们可能会继续这样做,除非发生一些非常糟糕的事情.
我问的是这是一种安全的做法,一种良好的做法还是一种黑客行为?
证据似乎表明它是安全的 - 但话又说回来,正如 ddimitrov 在评论中所说 - 由于未发布的更改,很可能不会发现微妙的线程错误,因为典型的机器只有几个核心,并且 L2/L3缓存是共享的。(L1 缓存是每个核心的,但通常非常小。)
如果您想保证不会因后台类加载而出现问题,那么坚持在 ETD 上加载类可能是最安全的。要维护实时 UI,请创建一个自定义类加载器,该加载器还在加载每个类之间泵送事件。(依赖项是可重入加载的,因此延迟只会在加载一个类的持续时间内发生。)假设该类加载器与您的应用程序打包在一起,那么它可以简单地将所有类加载推迟到它的类加载器。
或者,可以扩展辅助事件队列,在单独的线程上运行(例如模式对话框和旋转库)。这意味着 Swing 可以在任何线程上运行,只要它只在一个线程上运行,并且意味着它必须是更新一致的(或者到目前为止我们都非常幸运!)在此基础上,您可以在主 EDT 上加载类,并启动辅助 EDT 来泵送 UI 事件,保持 UI 响应 - 与模式对话框的功能相同。Spin 实用程序将为您泵送 EDT 事件,或者您也可以手动生成新的 EDT。
| 归档时间: |
|
| 查看次数: |
509 次 |
| 最近记录: |