Java 使用线程安全对局部和全局变量进行垃圾收集

Java Garbage collection against Local and Global variable with Thread Safe

以下哪个代码片段在 TIME 方面的垃圾收集效率更高

Class Test{...}

局部变量

private void function(){
   Test test = new Test();
    ....
}

全局变量

Test test = null; 
private void function(){   
   if(test == null){
     test = new Test();   
   } 
}

Let assume function() call frequently

编辑

你们都很好。回答得很好。 现在我要说

CASE-1 is more GC efficient than CASE-2 but on the other hand CASE-1 is not thread safe. So both having pros and cons

.

好吧,这取决于函数的使用以及对象在问题集中被定义为做什么。我总是说,只在需要时创建对象。没有理由让一个对象闲置不被使用。如果您计划在您的函数之外使用该对象,您将希望首先将其全局初始化为 null,然后在需要时创建该对象。

您不必担心 Java 的垃圾收集效率。这是有效的。只要你不是不断动态地制作 100 上 100 和更多对象,我就不会担心。

如果构造函数有副作用,您的两个选项会做两件不同的事情。


如果 Test 携带状态,选项 1 和选项 2 可能不再等效(并且选项 2 可能不是线程安全的)。

恰当的例子:许多人错误地使用了 Java 的日期或数字格式对象,例如选项 2。这效果不佳,因为它们不是线程安全的。


假设 Test 是完全无状态的并且调用构造函数没有副作用(你似乎暗示了这两者),选项 3 怎么样:

private static final Test test = new Test();

private void function(){
    .....
}

根本没有 GC activity。


或者,如果 Test 确实携带状态或者在某种程度上不是线程安全的,并且您想在紧密循环中调用 function,选项 4:

private void function(Test test){
}

void theCaller(){
    Test test = new Test();
    for (int i=0; i<10000; i++) {
       function(test);
    }
}

由于该方法是 private 您可以自由地移动到不太方便的方式来以性能的名义调用它。

在情况 1 中,创建了一个测试,并且在每次调用时都符合 GC 的条件,这会产生大量垃圾。在情况 2 中,它被创建一次并且可能永远不会被 GC。

为什么我们不总是使用选项 2 - 它可能不是线程安全的。让我们用 SimpleDateFormat 和 function() 替换 Test 将需要同步,否则它将无法在多线程应用程序中工作。同步也很昂贵。所以我们需要决定哪个选项是每次新对象或同步更好。