Java Singleton与静态-是否有真正的性能优势?
我正在合并一个CVS分支,其中最大的变化之一是用具有静态初始化块和所有静态方法的抽象类替换Singleton模式的任何地方。
这是值得保留的东西,因为它将需要合并很多冲突,对于这种重构我值得考虑的是哪种情况?
我们正在Weblogic 8.1(因此是JDK 1.4.2)下运行此应用程序
对不起托马斯,让我澄清一下..
HEAD版本具有传统的单例模式(私有构造函数,getInstance()等)
分支版本没有构造函数,是"公共抽象类",并将对象上的所有方法修改为"静态"。私有构造函数中曾经存在的代码被移到静态块中。
然后,该类的所有用法都会更改,这会导致合并中出现多个冲突。
在某些情况下,会进行此更改。
解决方案
回答
这个讨论有帮助吗? (我不知道链接到另一个编程论坛是否是忌讳的,但我宁愿不只是引用整个讨论=)
Sun关于这个问题的讨论
裁决似乎是,尽管从技术上讲静态方法更有效,但在大多数情况下它并没有产生太大的影响。
回答
从严格的运行时性能角度来看,差异实际上可以忽略不计。两者之间的主要区别在于"静态"生命周期链接到类加载器,而对于单例来说,它是常规实例生命周期。通常最好还是远离ClassLoader业务,避免一些棘手的问题,尤其是当我们尝试重新加载Web应用程序时。
回答
如果我的原始帖子是正确的理解,并且Sun所进行的讨论是准确的(我认为可能是正确的),那么我认为我们必须在清晰度和性能之间做出权衡。
问问自己以下问题:
- Singleton对象是否使我正在做的事情更清楚?
- 我是否需要一个对象来执行此任务,或者它更适合于静态方法?
- 我是否需要不使用Singleton才能获得的性能?
回答
如果需要存储任何状态,我将使用单例,否则将使用静态类。实例化某个东西,即使是单个实例,也没有意义,除非它需要存储一些东西。
回答
根据我的经验,唯一重要的是在单元测试中哪个更容易模拟。我一直觉得Singleton更容易和自然地嘲笑出来。如果组织允许我们使用JMockit,则无所谓,因为我们可以克服这些问题。
回答
静态对扩展性不利,因为静态方法和字段不能被子类扩展或者覆盖。
这对于单元测试也很不利。在单元测试中,由于无法控制类加载器,因此无法避免其他测试的副作用蔓延。在一个单元测试中初始化的静态字段将在另一个单元测试中可见,或者更糟的是,同时运行测试将产生不可预测的结果。
少量使用时,单例通常是可以的模式。我更喜欢使用DI框架,并让它为我管理实例(可能在Guice中的不同范围内)。
回答
编写一些代码来衡量性能。答案将取决于JVM(Sun的JDK的性能可能不同于JRockit),并且VM标记应用程序使用。