2012-04-08 10 views
1

Ich bin für die Erteilung einer einmaligen Kopie jedes Objekts in Runtime ein Singleton mit:Singleton über Sammlungen von Objekten in Java und Garbage Collector

Car object1= CarFactory.createCar(id); 

wo die createCar Methode ist:

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); 
    } 
} 

Das Problem ist, dass bei dieser Methode jedes Auto aufgrund der "Autosammlung" immer eine Referenz hat und der Objektspeicher nie freigegeben wird. Wie kann ich es verbessern?

+1

Sollte nicht '' static' sein cars' ? – Jeffrey

+0

Ja, es war ein Transcript-Fehler – Addev

+0

Das erste, was ich tun würde, ist das Entfernen der veränderlichen Statik. –

Antwort

2

Verwenden Sie eine WeakReference, um die Objekte zu umbrechen, bevor Sie sie in die Liste einfügen. Beispiel:

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(); 
    } 
} 

Hinweis: Dies ist kein Produktionscode. Sie müssen einige Sicherheitsvorkehrungen treffen, bevor Sie es verwenden.

+0

Problem: WeakReference.equals überprüft nicht, worauf es verweist, so dass der Index immer -1 ist, benutze stattdessen eine Iterator-Schleife (und entferne die Schwachstellen, die bereits gesammelt wurden) –

+0

@ratchetfreak Wie gesagt: Definitiv kein Produktionscode. :-) – nfechner

1

I angenommen Sie könnten eine Liste von WeakReference s führen. Eine schwache Referenz ist nicht stark genug, um ein Objekt davon abzuhalten, Müll zu sammeln.

Ex:

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! 

Allerdings, wenn Sie eine große Anzahl von Car s und Speichern sind zu schaffen ist tatsächlich ein Problem, es ist wahrscheinlich nicht die Mühe wert.

1

es ist ein bisschen wie ein Hack, aber Sie können

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; 
    } 
} 

beachten Sie, dass Sie die WeakRef als Wert benötigen verwenden, da der Wert einer starken ref

betrachtet
+0

Danke für deine Antwort, aber es funktioniert nicht, weil cars.get (result) immer zurückfährt (sogar überschreibe gleich Methode bei Car) – Addev

+0

@Addev hast du auch Cars 'hashcode() 'überschrieben (gib einfach id zurück) –

Verwandte Themen