基于线程安全的局部和全局变量的Java垃圾收集

基于线程安全的局部和全局变量的Java垃圾收集,java,garbage-collection,thread-safety,global-variables,local-variables,Java,Garbage Collection,Thread Safety,Global Variables,Local Variables,以下哪一段代码在时间上更有效地进行垃圾收集 Class Test{...} 局部变量 private void function(){ Test test = new Test(); .... } Test test = null; private void function(){ if(test == null){ test = new Test(); } } 全局变量 private void function(){ Test

以下哪一段代码在时间上更有效地进行垃圾收集

Class Test{...}
局部变量

private void function(){
   Test test = new Test();
    ....
}
Test test = null; 
private void function(){   
   if(test == null){
     test = new Test();   
   } 
}
全局变量

private void function(){
   Test test = new Test();
    ....
}
Test test = null; 
private void function(){   
   if(test == null){
     test = new Test();   
   } 
}
让我们假设函数()经常调用

编辑

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

案例1比案例2更具GC效率,但另一方面,案例1 不是线程安全的。所以两者都有利弊


.

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


您不应该担心Java的垃圾收集效率。效率很高。只要你没有不断地动态生成100个或更多的对象,我就不会担心它。

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


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

举个例子:许多人错误地使用Java的日期或数字格式对象,如选项2。这不起作用,因为它们不是线程安全的


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

private static final Test test = new Test();

private void function(){
    .....
}
根本没有GC活动


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

private void function(Test test){
}

void theCaller(){
    Test test = new Test();
    for (int i=0; i<10000; i++) {
       function(test);
    }
}
private void函数(测试){
}
使调用方无效(){
测试=新测试();

对于(int i=0;i,在案例1中,会创建一个测试,并在每次调用时符合GC条件,这会创建大量垃圾。在案例2中,它只创建一次,可能永远不会进行GCed


为什么我们不总是使用选项2?它可能不是线程安全的。让我们用SimpleDataFormat和function()替换测试将需要同步,或者在多线程应用程序中无法工作。同步也很昂贵。因此,我们需要决定哪种选项更适合每次使用新对象或同步。

我更担心使用“全局变量”(在我看来像实例字段)的副作用。例如丢失线程安全性。全局变量场景使用延迟加载,这将避免每次执行
函数()时不断重新实例化
测试
被调用。这也会减少垃圾收集器所做的工作。不利的是,你会被永久内存中的
Test
实例卡住,如果该实例不经常使用,这将是一种浪费。@TimBiegeleisen-你能详细说明一下吗?@TimBiegeleisen我知道内存和性能都是相反的。Anywa你给出的答案是案例2更有效。谢谢!@AmitYadav-在这种情况下,答案是案例2,因为GC会更少。删除了我的答案:)。@James Combs这是实时函数()中的简单说明经常打电话。我们知道GC非常有效,但我想知道哪一个是避免GC呼叫的好方法?请检查@Thilo提供的答案