在Java中,如果我有很多本地对象,如果我将它们定义为实例变量,它会运行得更快吗?例如,如果多次调用我的func1(),比如在循环中调用,那么每次调用函数时,JVM是否会继续实例化并垃圾收集list2?相反,我应该重用相同的list1对象来防止垃圾收集和实例化开销吗?
class A {
List list1 = new ArrayList();
private void func1() {
list1.clear();
// add new objects list1
List list2 = new ArrayList();
// add new objects to list2
}
}
优化器是否足够智能以跳过垃圾收集并自动重用该对象?
答案 0 :(得分:2)
GC优化不是决定Local
vs Instance
变量的正确方法。如果需要的变量由多个实例方法使用,那么使用实例变量是有意义的。
你是对的,局部变量使用可能会增加GC活动。
答案 1 :(得分:1)
在决定是使用本地变量还是实例变量之前,可能需要考虑各种用例。性能可能因用例而异。
Effective Java中可以找到一个很好的例子:Item 5 - “避免创建不必要的对象”
答案 2 :(得分:1)
还要考虑实例变量值的线程安全性。同一对象的两个线程需要同步访问实例变量数据,但在这里它始终是一个新的局部变量数据对象。
答案 3 :(得分:1)
如果 - 且仅 - 您已证实,由于对象创建而导致GC出现问题,您应该考虑合并已验证的对象成本高昂。
为此,你不必重新发明任何轮子,你可以使用Javolutions utils来实现它,FastList在这种情况下使用FastList.newInstance()调用:
List<Whatever> newOrReusedList = FastList.newInstance();
...以及相应的FastList.recycle(FastList)
调用,以使其可供重复使用。 (谢谢 @JIV ,我忘了添加这一点。)
(请注意,使用javolutions Fast *类可能会导致不同的性能:它们面向可预测的性能(实时系统)而不是速度,因此可能存在用例,当它们的执行速度比java.lnag的速度慢时)
答案 4 :(得分:1)
我用jdk1.6编写了一个小测试程序,在
下面结果:
* dostuff为594ms(创建本地)
* dostuff2的58ms(使用实例)
public class Test {
static long counter=0;
public static void main(String[] args) {
long t1 = System.nanoTime();
Test test = new Test();
for (int i=0;i<1000000000;i++) {
test.doStuff();//or dostuff2
}
long t2 = System.nanoTime();
System.err.println((t2-t1)/1000000);
System.err.println(counter); // to check it wasnt optimised away
}
private void doStuff() {
List l = new ArrayList();
if (l!=null) {
counter++;
}
}
List l2 = new ArrayList();
private void doStuff2() {
if (l2!=null) {
counter++;
}
}
}
结果,似乎实例比使用本地更快,正如人们所期望的那样。
然而,似乎你至少在我的电脑上节省了大约0.5亿美元的物品,所以你需要真正需要性能增益来证明它的合理性