2012-04-08 66 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