2012-04-08 64 views
1

我使用的是单有关在运行时给予每个对象的唯一副本:辛格尔顿在Java中对象的集合,垃圾收集

Car object1= CarFactory.createCar(id); 

其中createCar方法是:

private static ArrayList<Car> cars= new ArrayList<Car>(); 

public static synchronized Car createCar(int id){ 
    Car result= new Car(id); 
    int index= cars.indexOf(result); 
    if (index==-1){ 
     cars.add(result); 
     return result; 
    } else { 
     return cars.get(index); 
    } 
} 

问题在于,通过这种方法,每辆车总是具有“汽车”集合的参考,并且对象的内存永远不会释放。我该如何改进它?

+1

不应该'cars'是'static' ? – Jeffrey 2012-04-08 19:49:13

+0

是的,这是一个成绩单的错误 – Addev 2012-04-08 19:51:18

+0

我会做的第一件事是删除可变静态。 – 2012-04-08 19:53:57

回答

2

使用一个WeakReference在将对象放入列表之前先包装这些对象。例如:

private static List<WeakReference<Car>> cars = new ArrayList<WeakReference<Car>>(); 

public static synchronized Car createCar(int id) { 
    WeakReference<Car> result= new WeakReference<Car>(new Car(id)); 
    int index= cars.indexOf(result); 
    if (index==-1){ 
     cars.add(result); 
     return result.get(); 
    } else { 
     return cars.get(index).get(); 
    } 
} 

注意:这不是生产代码。在使用之前,你必须建立更多的保护措施。

+0

问题:WeakReference.equals不检查它引用的内容,所以索引总是-1,而是使用迭代器循环(并删除已经收集的弱引用) – 2012-04-08 20:17:50

+0

@ratchetfreak正如我所说:绝对不是生产代码.. :-) – nfechner 2012-04-09 07:23:24

1

假设你可以保留一个列表WeakReference s。弱引用不足以保持垃圾收集对象。

例:

List<WeakReference<Point>> list = new ArrayList<>(); 
    Point p = new Point(); 
    list.add(new WeakReference<>(p)); 
    System.out.println(p); 
    System.out.println(list.get(0).get()); 

    p = null; 

    System.gc(); 
    System.gc(); 
    System.gc(); 
    System.gc(); // hopefully the GC collects p by now 

    System.out.println(list.get(0).get()); // null! 

但是,除非你创建了大量的Car S和内存实际上的问题,它可能是不值得的麻烦。

1

这是一个黑客位,但你可以使用

WeakHashMap<Car,WeakReference<Car>> cars=new WeakHashMap<Car,WeakReference<Car>>(); 

public static synchronized Car createCar(int id){ 
    Car result= new Car(id); 
    WeakReference<Car> weakCar=cars.get(result); 
    if(weakCar==null){ 
     cars.put(new WeakReference(result)); 
     return result; 
    } 
    Car val= weakCar.get(); 
    if (val==null){//it may have been collected between cars.get() and weakCar.get() 
     cars.put(new WeakReference(result)); 
     return result; 
    } else { 
     return val; 
    } 
} 

请注意,您所需要的weakref的价值,因为价值被认为是一个强大的裁判

+0

感谢您的回答,但它不起作用,因为cars.get(result)返回始终运行(甚至在Car重载equals方法) – Addev 2012-04-08 20:43:47

+0

@Addev是否也覆盖了Car's'hashcode()'(仅返回id) – 2012-04-08 20:47:00