使用静态初始化块来提高性能

时间:2012-09-05 09:08:27

标签: java performance static-initialization

鉴于生产中使用的现有代码库包含一个类A,该类包含一个方法,该方法使用setter填充另一个POJO类B的N个字段,并将POJO返回给调用者,并且假定B类的所有实例都不同只考虑两个字段,即N-2个字段在B类的所有实例中都是相同的,如果A类具有对B类的静态引用并且初始化B类的不改变的字段,那么是否会有任何性能提升在一个静态初始化块?这样,A类中每次调用时填充B类N个字段的方法现在只需要填充两个不同的字段。这也将消除为每次调用A类中的方法创建类型B的新对象的需要。这种方法在多线程应用程序中有什么含义?

或者,我们可以声明B类中不会更改为静态的所有字段,以便A类中的方法仅设置每次调用更改的字段。无论哪种方式,性能增益是否值得,或者这种变化是否属于过早优化?

示例:

class A { 
     private static B b = new B(); 

     static {
         b.setSystem("MySystem");
         b.setVersion("1.1");
     }

     public B getB(String name) {
         b.setName(name);
         return B;

     }
}

3 个答案:

答案 0 :(得分:2)

  

鉴于B类的所有实例仅在两个字段

方面有所不同

所以我知道你有多个B

的实例
  

这也消除了为每次调用A类方法创建类型B的新对象的需要。

但是现在你只有一个B实例 - 如果A更改了这两个字段,代码中所有引用该B实例的位置都会看到更改(假设正确同步)。

=>目前尚不清楚您是否需要一个或多个B实例。

  

这种方法在多线程应用程序中有什么含义?

如果您共享B个交叉线程的相同实例,则需要确保在编写和读取B的属性时使用正确的同步。

  

或者,我们可以声明B类中不会更改为静态

的所有字段

你的意思是最终?

  

无论哪种方式,性能增益是否值得,或者这种变化是否属于过早优化?

它认为确实符合资格。特别是因为你似乎并不完全确定你需要什么。和往常一样的建议:简单易行。 IF 性能不够好,可以分析并确定代码的哪些部分需要改进。

如果您知道自己将处于多线程环境中,那么您应该避免任何静态和可变的事情 - 这将使您的生活更轻松并限制并发错误的风险。

理想情况下,(1)尽量不要在线程之间共享对象 - 如果你不能,那么(2)尝试共享不可变对象 - 如果你不能(3)确保你使用正确的同步并且你知道你在做什么。

答案 1 :(得分:0)

如果您只保留一个类B的实例,您可以根据需要修改并返回该方法,那么您将不得不遇到麻烦:调用者不能依赖包含数据的返回对象请求。在单线程应用程序中,如果在两者之间存在对方法的不同调用,则存储该值并稍后访问它将导致麻烦。在多线程应用程序中,内容甚至可能在没有来自当前线程的调用的情况下发生更改,因为另一个线程可能会调用该方法并导致对象发生更改。对象甚至可能处于不一致状态。

在某些情况下,可以安全合理地使用它,但根据您提供的一般说明,我建议不要这样做。也许更好的解决方案是将B类的不变部分分解出来,使B仅保存两个变化的值,并引用另一个保持不可修改部分的对象。当然,这仅适用于您控制B的实现。

答案 2 :(得分:0)

  

给定一个包含A类的方法,该方法使用setter

填充另一个POJO B类的N个字段

所以A有B的实例或B的实例列表?

  

并将POJO返回给调用者,并且假定B类的所有实例仅在两个字段方面不同,即N-2个字段在所有B类实例中都是相同的,

为什么不直接初始化B本身的N-2字段。

  如果类A具有对类B的静态引用并初始化在静态init块中没有更改的类B的字段,那么会有任何性能提升吗?这样,A类中每次调用时填充B类N个字段的方法现在只需要填充两个不同的字段。这也将消除为每次调用A类中的方法创建类型B的新对象的需要。这种方法在多线程应用程序中的含义是什么?

如果您使用Static,则B将成为A类的一部分,而不是A的对象,因此对于所有A个实例,B是否通用?您真的想要吗?

  

或者,我们可以声明B类中不会更改为静态的所有字段,以便A类中的方法仅设置每次调用更改的字段。无论哪种方式,性能增益是否值得,或者这种变化是否属于过早优化?

请提供一些代码。 在我看来,静态块应仅用于配置对象初始化。