2012-06-04 14 views
10

Quiero cerrar correctamente el objeto Cerrar cuando ya no se hace referencia a otros hilos.Uso de ReferenceQueue y WeakReference

Escribí una pequeña prueba, pero después de poner en cola el objeto el método get devuelve nulo, es decir, el método poll devuelve el objeto apropiado que no tiene referente.

public static void main(String[] args) 
    { 
    ReferenceQueue<Closeable> reaped = new ReferenceQueue<Closeable>(); 
    Closeable s = <SOME CLOSEABLE IMPL>; 
    WeakReference<Closeable> ws = new WeakReference<Closeable>(s, reaped); 
    s = null; 

    System.gc(); 
    Closeable ro = (Closeable)reaped.poll().get(); 
    ro.close(); 
    } 

Gracias de antemano. Cualquier ayuda será apreciada.

Respuesta

7

Primero, si solo se trata de cerrar, use PhantomReference. A continuación, de la cola de referencia, poll() no garantiza que obtendrá la referencia de vuelta. y nunca recuperarás el objeto real (referente).

Si quiere asegurarse de que su Closeable s esté cerrado, debe hacer un seguimiento de ellos, digamos en un Map<Reference<?>, Closeable>. Entonces cuando poll() su cola de referencia, eventualmente obtendrá el ref, entonces usted tiene que usarlo para obtener el Closeable del mapa.

class MyThing { 
     Closeable c; 
    } 

    Map<Reference<MyThing>, Closeable> m = new HashMap(); 
    ReferenceQueue<MyThing> reaped = new ReferenceQueue<MyThing>(); 

    MyThing mt = new MyThing(); 
    mt.c = new MyClosable(); 

    Reference<MyThing> pref = new PhantomReference<MyThing>(mt, reaped); 
    m.put(pref, mt.c); 

    mt = null; 


    System.gc(); 
    Reference<MyThing> rf = reaped.poll(); 
    while (rf != null) { 
    m.get(rf).close(); 
    rf = reaped.poll(); 
    } 

Nota Si usted no tiene una verdadera razón para hacer esto o si no entiende lo que está haciendo en realidad, NO hacer este tipo de cosas.

puede cerrar los archivos en finally y por cierto si se trata de archivos, tomas de corriente, etc, que están cerradas para usted (que ya implementan finalize()

+0

Hola gracias por la respuesta tan rápida, se trata de IndexSearcher de de Lucene. – yan

+0

Acabo de probarlo, después del System.gc(); el tamaño ReferenceQueue es 0. – yan

+0

@yan no hay garantía de que tus objetos obtengan GCes después de 'System.gc()' ni siquiera cuando salgas de la JVM. no use la finalización para su lógica de negocios. Está allí solo para propósitos especiales como el almacenamiento en caché y (eventualmente) la prevención de fugas de recursos. No puede dejar decir 'commit()' o 'rollback()' DB transacciones en el finalizador –