Domanda

Questo post di blog dimostra un modo di implementare un idioma id mutex per stringa. Gli ID stringa utilizzati devono rappresentare gli ID HttpSession.

  1. Perché dobbiamo includere un WeakReference attorno alle istanze di Mutex? Non è meglio creare semplicemente una mappa da String - > Mutex?
  2. Perché dobbiamo chiamare put due volte?

    public Mutex getMutex( String id )
    {                                  
        Mutex key = new MutexImpl( id );
        synchronized( mutexMap )
        {
            WeakReference<Mutex> ref = mutexMap.get( key );
            if( ref == null )
            {
                mutexMap.put( key, new WeakReference<Mutex>( key ) );
                return key;
            }
            Mutex mutex = ref.get();
            if( mutex == null )
            {
                mutexMap.put( key, new WeakReference<Mutex>( key ) );
                return key;
            }
            return mutex;
        }
    }
    
È stato utile?

Soluzione

Loop e Bruno Conde l'ho praticamente coperto, ma da quando ho scritto quel codice ...

L'obiettivo del progetto era evitare che l'utente chiamasse un meccanismo di rilascio: il mutex è idoneo per la garbage collection quando l'utente non lo fa più riferimento.

  

Perché dobbiamo avvolgere un riferimento debole   intorno alle istanze di Mutex?

La mappa è una WeakHashMap :

private final Map mutexMap = new WeakHashMap();

Questa mappa viene utilizzata per mantenere un riferimento al mutex, ma se si utilizza lo stesso oggetto per la chiave e il valore, l'oggetto non è idoneo per la garbage collection. Javadoc:

  

Nota di implementazione: gli oggetti valore   in una WeakHashMap sono gestiti dall'ordinario   riferimenti forti. Quindi la cura dovrebbe essere   preso per garantire che gli oggetti valore lo facciano   non si riferiscono fortemente alle proprie chiavi,   direttamente o indirettamente, poiché   ciò impedirà alle chiavi di essere   scartato. Si noti che un oggetto valore   può fare riferimento indirettamente alla sua chiave tramite   la WeakHashMap stessa; cioè un   valore oggetto può riferirsi fortemente   qualche altro oggetto chiave il cui associato   valore oggetto, a sua volta, si riferisce fortemente   alla chiave del primo oggetto valore.   Un modo per affrontare questo è quello di avvolgere   si valutano all'interno   Riferimenti deboli prima di inserire, come   in: m.put (chiave, nuovo   WeakReference (valore)) e quindi   da scartare su ogni get.


  

Non è vero   meglio creare semplicemente una mappa da   String - > Mutex?

Quando verrà raccolto il valore di quella stringa? Lo stesso riferimento viene passato ogni volta? Ha intern () stato invitato? Se chiamo stagista, quanto durerà la String? Se una stringa era la chiave, il mutex potrebbe non essere idoneo per la garbage collection molto tempo dopo che non è necessario mantenerne un riferimento.


  

Perché dobbiamo chiamare put due volte?

Esistono due casi da gestire fino a quando il metodo non può ottenere un forte riferimento al mutex nella mappa:

  • il WeakReference ha spazzatura raccolta (o non è mai stata lì in primo luogo)
  • i contenuti di WeakReference sono rifiuti raccolti dopo che il riferimento è stato acquisito

put sarà invocato solo una volta; il metodo ritorna immediatamente dopo.

(The WeakReference potrebbe essere riutilizzato nella seconda frase, ma non vedo che sarebbe un miglioramento significativo.)


Naturalmente, se qualcuno riesce a trovare un difetto nel codice, fammi sapere e lo correggerò felicemente. Inoltre, i test unitari cercano di verificare che l'implementazione non perda, quindi sentiti libero di modificare il codice e vedere cosa succede quando esegui i test.

Altri suggerimenti

Gli oggetti valore in una WeakHashMap sono mantenuti da normali riferimenti forti. Pertanto, occorre prestare attenzione a garantire che gli oggetti valore non si riferiscano fortemente alle proprie chiavi, né direttamente né indirettamente, poiché ciò impedirà che le chiavi vengano scartate. Si noti che un oggetto valore può fare riferimento indirettamente alla sua chiave tramite la stessa WeakHashMap; vale a dire, un oggetto valore può riferirsi fortemente a qualche altro oggetto chiave il cui oggetto valore associato, a sua volta, si riferisce fortemente alla chiave del primo oggetto valore. Un modo per gestirlo è avvolgere i valori all'interno di WeakReferences prima di inserirli, come in: m.put (chiave, nuovo WeakReference (valore)), e quindi scartarli ad ogni get.

1 - @Loop ha un buona risposta .

2 - Supponendo che le voci siano racchiuse in WeakReferences, il secondo put è necessario perché WeakReference può essere raccolto prima che l'esecuzione raggiunga la linea:

 Mutex mutex = ref.get();

In questo caso:

  • la voce potrebbe non esistere già nella map
  • se esiste, può essere raccolto prima dell'esecuzione di Mutex mutex = ref.get ();

Direi che i WeakReference sono usati solo perché devono fare riferimento agli ID di sessione http. Non puoi sempre essere sicuro al 100% di ricevere una notifica che termina una sessione in modo da causare una mappa in continua crescita.

La prima volta che chiami put è perché la mappa non contiene la tua chiave. La seconda volta è perché la mappa conteneva la chiave ma il riferimento non esisteva più.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top