Domanda

So che c'è un WeakHashMap in java.util , ma poiché usa WeakReference per tutto, a cui fa riferimento solo questo Mappa , gli oggetti referenziati andranno persi nel prossimo ciclo GC. Quindi è quasi inutile se si desidera memorizzare nella cache dati casuali, che è molto probabile che vengano richiesti di nuovo senza essere strettamente collegati per il resto del tempo. La soluzione migliore sarebbe una mappa, che usa invece SoftReference , ma non ne ho trovata una nel pacchetto Java RT.

È stato utile?

Soluzione

Modifica (agosto 2012):

Si scopre che attualmente la migliore soluzione sono probabilmente le classi Cache di Guava 13.0, spiegate su Guava's Wiki - questo è quello che userò. Supporta anche la creazione di un SoftHashMap (vedi CacheBuilder.newBuilder (). SoftKeys () ), ma probabilmente non è quello che vuoi, come spiega l'esperto Java Jeremy Manson (sotto troverai il link).


Non che Conosco (novembre 2008), ma tu tipo trova qualche implementazione di SoftHashMap in rete.

Come questo: SoftHashMap / a> o questo .


Modifica (novembre 2009)
Come Matthias menziona nei commenti, la Google Guava MapMaker usa SoftReferences:

  

Un costruttore ConcurrentMap , che fornisce una combinazione di queste funzionalità:

     
      
  • tasti soft o deboli,
  •   
  • valori deboli o deboli,
  •   
  • scadenza temporizzata e
  •   
  • calcolo dei valori su richiesta.
  •   

Come menzionato in questa discussione , un'altra Candidato JSR166y:

jsr166y.ConcurrentReferenceHash / <> p>

  

Fornisce una mappa di riferimento simultanea alternativa all'implementazione di Google (che si basa su un thread in background per eliminare le voci)


Modifica (agosto 2012)

L'implementazione di Google utilizza un thread in background solo quando è richiesta la scadenza temporizzata delle voci. In particolare, utilizza semplicemente java.util.Timer , che non è così invadente come avere un thread in background separato.

Jeremy Manson consiglia, per qualsiasi cache, di utilizzare questa funzione per evitare i pericoli di SoftReference: http://jeremymanson.blogspot.de/2009/ 07 / how-hotspot-decide-to-clear_07.html

C'è un'altra implementazione da Apache Commons , ovvero org.apache.commons.collections.map.ReferenceMap ; non supporta la rimozione temporizzata, ma supporta la scelta se le chiavi debbano essere confrontate per identità o per uguaglianza. Inoltre, questa implementazione non è simultanea: può essere sincronizzata, ma funziona meno bene sotto gli accessi da più thread.

Altri suggerimenti

Conosco due librerie che offrono un'implementazione di SoftHashMap:

  1. Apache Commons : org.apache.commons.collections.map.ReferenceMap

  2. Collezioni di Google : com.google.common.collect.ReferenceMap

Esiste un'implementazione di esempio nella numero 98 della newsletter di specialisti Java

Apache Shiro viene fornito con una SoftHashMap progettata per la memorizzazione nella cache. È basato sull'articolo pubblicato da jb sopra e concesso in licenza sotto Apache v2. Puoi trovare la documentazione qui e il codice sorgente qui .

Hai mai pensato di utilizzare un LRUMap invece di una soft HashMap? Ottieni un maggiore controllo su ciò che viene memorizzato (o almeno, quanto).

Se si desidera implementare un softreferences della cache è sicuramente un'idea migliore dei riferimenti deboli, ma mette l'intera politica di rimozione della cache nelle mani del garbage collector. che probabilmente non è quello che vuoi.

Se la politica di rimozione della cache è importante, dovrai probabilmente farlo da solo utilizzando riferimenti regolari. Tuttavia dovrai decidere quando espellere gli oggetti e quali espellere. Se vuoi perdere qualcosa solo quando stai esaurendo lo spazio heap, puoi eseguire una query sullo spazio heap disponibile tramite:

Runtime.getRuntime().getFreeMemory();

Quindi, una volta che la memoria libera scende al di sotto di una certa quantità, puoi iniziare a far cadere oggetti. Oppure potresti semplicemente implementare una dimensione massima per la cache e usarla per decidere quando rilasciare le cose.

ecco una cache LRU ho progettato con O (1) tempo di inserimento, cancellazione e ricerca, con un numero massimo configurabile di elementi. Se vuoi una cache, questa sarà una soluzione migliore di una SoftHashMap.

Le softreferenze sono un ottimo modo per creare una cache coltivabile. Quindi la soluzione ideale sarebbe quella di utilizzare una SoftHashMap insieme a una normale cache di dimensioni fisse. tutti gli inserimenti nella cache vanno sia nella cache fissa che nella mappa hash software, quindi per fare riferimento a qualcosa basta vedere se è nella hashmap software (e aggiornare il tempo di riferimento nella cache). in questo modo tutti gli elementi più importanti (in base alla LRU, alla MFU della politica selezionata, ...) non verranno mai rimossi perché sono fortemente referenziati nella cache ma rimarrai aggrappato a più cose (senza controllo delle politiche) finché in quanto memoria sufficiente.

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