16

Do SoftReference e WeakReference aiutano davvero solo se creati come variabili di istanza? C'è qualche vantaggio nell'utilizzarli nell'ambito del metodo?Utilizzo di Java ReferenceQueue

L'altra grande parte è ReferenceQueue. Oltre a essere in grado di tracciare quali riferimenti sono determinati garbage, è possibile utilizzare Reference.enqueue() per registrare forzatamente un oggetto per la garbage collection?

Ad esempio, varrebbe la pena di creare un metodo che richiede alcune risorse di memoria pesanti (racchiuse da riferimenti forti) in un oggetto e crea dei riferimenti per accodarli?

Object bigObject; 
public void dispose() { 
    ReferenceQueue<Object> queue = new ReferenceQueue<Object>(); 
    WeakReference<Object> ref = new WeakReference<Object>(bigObject, queue); 
    bigObject = null; 
    ref.enqueue(); 
} 

(Immaginate di oggetto in questo caso rappresenta un tipo di oggetto che utilizza molta memoria ... come BufferedImage o qualcosa)

Questo ha alcun effetto realistico? O è solo uno spreco di codice?

+0

Mildly related: https://codereview.stackexchange.com/q/28534/4394 – Pacerier

risposta

26

un linguaggio comune con le code di riferimento è quello di esempio sottoclasse WeakReference per allegare le informazioni necessarie per ripulire le cose e quindi per eseguire il polling di un ReferenceQueue per ottenere le attività di pulizia.

ReferenceQueue<Foo> fooQueue = new ReferenceQueue<Foo>(); 

class ReferenceWithCleanup extends WeakReference<Foo> { 
    Bar bar; 
    ReferenceWithCleanup(Foo foo, Bar bar) { 
    super(foo, fooQueue); 
    this.bar = bar; 
    } 
    public void cleanUp() { 
    bar.cleanUp(); 
    } 
} 

public Thread cleanupThread = new Thread() { 
    public void run() { 
    while(true) { 
     ReferenceWithCleanup ref = (ReferenceWithCleanup)fooQueue.remove(); 
     ref.cleanUp(); 
    } 
    } 
} 

public void doStuff() { 
    cleanupThread.start(); 
    Foo foo = new Foo(); 
    Bar bar = new Bar(); 
    ReferenceWithCleanup ref = new ReferenceWithCleanup(foo, bar); 
    ... // From now on, once you release all non-weak references to foo, 
     // then at some indeterminate point in the future, bar.cleanUp() will 
     // be run. You can force it by calling ref.enqueue(). 
} 

Ad esempio, la struttura interna di CacheBuilder attuazione del Guava quando weakKeys sono selezionate uses questo approccio.

+0

Quindi è in attesa che il riferimento sia accodato, quindi invocando cleanUp? Hanno mai effettivamente invocato enqueue()? – bgroenks

+0

Come per il ['enqueue' doc] (http://docs.oracle.com/javase/6/docs/api/java/lang/ref/Reference.html#enqueue()), non è effettivamente necessario chiamare 'enqueue'. L'oggetto di riferimento viene aggiunto alla coda di riferimento quando l'oggetto di riferimento ottiene GC'd. –

+1

Dice anche che il GC non lo usa. Allora perché esiste Mi chiedo? – bgroenks

5

Se un oggetto ha solo WeakReference s (o nessun riferimento!) Verso di esso, può essere raccolto automaticamente ogni volta che Java ha bisogno di lasciare più spazio nella memoria. Quindi, usi WeakReference s ogni volta che vuoi che un oggetto rimanga in memoria, ma non ne hai bisogno per rimanere COSI male (ad esempio se Java ha bisogno di raccogliere i dati inutili, nessun problema, puoi recuperarlo in qualche modo e nel mezzo tempo Java ha prestazioni migliori)

Accoppiamento a WeakReference consente di iterare il ReferenceQueue e determinare quali riferimenti sono stati garbage collector e quali no. Questo è tutto, quindi fallo solo se devi saperlo.

Per saperne di più: http://weblogs.java.net/blog/2006/05/04/understanding-weak-references

+0

Lo so. Ma la mia domanda è: il metodo di accodamento() costringe il WeakReference a essere garbage collection o registrato per la garbage collection? – bgroenks

+0

No. Se hai bisogno che venga raccolto automaticamente in questo momento, rimuovi tutti i riferimenti forti e comunica al garbage collector di eseguire. – Patashu

+0

Non penso che sia garantito farlo comunque. Cosa fa realmente enqueue()? – bgroenks

3

Una cosa comune da fare è creare mappe di riferimenti software.

Sto mostrando la mia vecchia scuola qui - i nuovi pacchetti Java probabilmente hanno modi molto più eleganti per farlo.

+0

Oh, aspetta, questa non è la tua domanda! È completamente irrilevante! – PaulMurrayCbr

+0

Onestamente, questo è in realtà un ottimo esempio del mondo reale di come utilizzare correttamente un riferimento debole/debole per inizializzare correttamente gli oggetti (senza condizioni di competizione o Blocco), che notifica altri thread in attesa ... Si è dimenticato di dire che no, la creazione e l'accodamento dei riferimenti non aiuta affatto ed è uno spreco di codice. Hai bisogno che tutti i TUO riferimenti non gc ad un oggetto grande vengano annullati (per non impedire GC ...) – Ajax

0

Non so qual è la domanda qui, ma:

1) ref morbido cercare di mantenere il riferimento fino JVM davvero bisogno di memoria. Ottimo per cache, specialmente per LRU. Guarda molti esempi in Guava.

2) Il ref debole non tenta di impedire a gc di liberare l'oggetto. Sono usati se vuoi sapere se quell'oggetto è ancora usato da qualche parte. Ad esempio, vengono utilizzati per memorizzare informazioni su thread e classi, in modo che quando il thread o la classe non vengono più utilizzati, è possibile scartare il metainfo relativo.

3) i phantom ref sono come deboli ma senza che tu possa fare riferimento all'oggetto reale. In questo modo puoi essere sicuro che passare il fantoccio in giro non può riprendere l'oggetto reale (questo è un rischio con ref debole).Anche i phantom ref stanno bloccando l'oggetto da raccogliere fino a quando non cancelli il rif.

ReferenceQueue: non si entra nella roba. gc farà per te. Ti permettono di sapere quando alcuni riferimenti vengono rilasciati, senza doverli controllare uno per uno.