Java:getInstance()Singleton性能

时间:2016-04-21 08:30:40

标签: java performance

我无法找到使用单一类的正确方法,这是最友好的方式。我有3种方法,也许有人可以用最有效的方式解释我:

1:

public functionA() {
    SingletonClassA.getInstance().callA();
    SingletonClassA.getInstance().callB();
    SingletonClassA.getInstance().callC();
    SingletonClassA.getInstance().callD();
    SingletonClassA.getInstance().callE();
}

2

public functionA() {
    SingletonClassA tmp = SingletonClassA.getInstance();
    tmp.callA();
    tmp.callB();
    tmp.callC();
    tmp.callD();
    tmp.callE();
}

3

SingletonClassA tmp = SingletonClassA.getInstance();       
public functionA() {
    tmp.callA();
    tmp.callB();
    tmp.callC();
    tmp.callD();
    tmp.callE();
}

我看到使用方法1的代码,但我认为更好的方法是2(如果其他函数也使用SingletonClassA则为3)。

我来自c-development,但我不太了解Java及其参考资料。我只是希望它不会消耗太多内存并且执行起来很快。

3 个答案:

答案 0 :(得分:3)

在谈论表现时,永远不要想(或正确地措辞:假设/相信)。

相反:阅读Java即时编译器及其功能。而且意外的是:大多数时候,JIT会将像你这样的微观优化想法转变为管道。如果您真的遇到问题,只能解决性能问题。然后:学习使用java分析器来衡量正在发生的事情。

意义:专注于SOLID设计;编写可读的,可维护的代码......这通常会导致良好的"代码无论如何;并且比花时间在Java上的这些东西更有价值。此外:如果您的代码是可维护的,那么为了解决某些性能问题,进行更改会更容易。

(是的,应该避免犯下愚蠢的错误;但是第一个也是最大的错误是假设这样做会对性能产生好/坏影响。)

附注:考虑不使用单例类,但枚举使用单个实例。

答案 1 :(得分:1)

使用包含单个实例的枚举。

如果你关心并发环境中的单例,并且你想要延迟初始化,请转到Initialization-on-demand pattern

答案 2 :(得分:0)

如果你想编写性能最好的版本,第三种方法非常接近,但你应该使用私有的最终静态变量,以避免不必要的额外查找:

private static final SingletonClassA singletonA = SingletonClassA.getInstance();       
public functionA() {
    singletonA.callA();
    singletonA.callB();
    singletonA.callC();
    singletonA.callD();
    singletonA.callE();
}

我认为你的Singleton的创建方式,以后不会改变,所以static也是一个不错的选择。静态将为每个类的实例节省4/8字节的内存(32/64位VM),因为该变量将不再是该类的潜在许多实例的一部分,它将只存在一次。

final提示编译器在初始声明后此变量不会更改,因此不需要对更改进行任何检查。请注意,这只是一个提示,可以使编译器的决策更容易。在大多数情况下,编译器可以自行确定。但是,向代码的读者提示只读变量也是一种好习惯,而final就是这样做的。

private确保变量不是可继承类部分的一部分,因此可以跳过对类层次结构的检查。然而,这更多是编译时性能增益,因为JVM总是可以精确地确定必须使用类层次结构中的哪个版本。

另请注意,类变量应始终具有明确的名称,以指明其用途。 tmp既不明确也不描述目的。

但是:未经优化的代码中的性能增益最多只有几纳秒,如果该函数是所谓的“热”函数的一部分(=经常调用它),它将进行优化远远超出您使用标准Java代码所能做的事情。因此,在这种特定情况下重写代码所带来的性能提升完全可以忽略不计。

除非您有特别的理由相信您的代码会妨碍性能,否则编写易于阅读和维护的代码总是比在较小的级别进行优化更好。 JVM在为您做这件事方面要好得多,因为它知道有关执行机器的更多细节。您在英特尔机器上进行的优化可能是i.E.导致代码在ARM系统上执行得更慢。

优化应始终从架构(全局)级别开始,并且只有在您测量并证明某些代码部分之后仍然太慢的情况下,您才应该开始考虑这种微级优化。