2010-02-12 12 views
9

Llegué anteriormente a la conclusión de que si necesita una igualdad basada en el valor de SoftReference (igual), entonces uno tenía un diseño incorrecto, excepto un interno de este. Esto sigue a Google Collections y Guava sin incluir dicha clase. Pero me he encontrado con un problema que creo que podría usar un objeto así.Uso potencial para SoftReference con igualdad de valor (igual)

Tenemos un sistema de gestión de activos en una granja de renderizado de efectos visuales con cientos de procesos ejecutando el mismo trabajo que solo difieren en el número de fotograma que representa. Tenemos una base de datos Oracle que necesita registrar todos los activos utilizados. En lugar de golpear a Oracle con insertos idénticos donde solo uno tendrá éxito en todos los trabajos, en el sistema de administración de activos de nivel medio podemos usar un HashSet para registrar si el objeto que se insertará en Oracle.

Podría utilizar un MapMaker de Google con un vencimiento, pero no quiero tener que preocuparme de que la caducidad sea correcta, hemos procesado en horas y algunos días. El uso de una referencia suave con igual igualdad suena como una forma mucho mejor para que la JVM administre la recolección de basura automáticamente.

Para otros problemas que queremos resolver con un ConcurrentHashMap con la recolección de basura, me gustaría utilizar una fuerte referencia en el HashMap como la clave para conseguir iguales() de igualdad y un SoftReference como el valor por lo que la JVM puede recoger la basura algo , pero en este caso, el valor no importa y no tengo un valor para ajustar en una referencia suave para poner allí. Por lo tanto, parece que usar una referencia suave con iguales() haría el truco.

¿Alguna otra sugerencia sobre esto?

+1

Me encanta su pregunta, me he estado preguntando sobre eso también hace poco – nanda

+0

¿No hace 'ResourceBundle' hacer algo como esto? –

+0

@nanda lo que se agrega a Oracle es una lista de activos (digamos nombres de archivos en un servidor NFS) generados dinámicamente; ResourceBundle no parece ser el adecuado. Solo necesito un HashSet para registrar que el nombre de archivo fue grabado en Oracle, así que otros 99 intentos de insertarlo no desperdician ciclos de CPU en Oracle. –

Respuesta

1

En la mayoría de los casos cuando se desea utilizar referencias suaves con Google Colecciones, debe llamar

MapMaker.softValues() 

Con claves de alta seguridad, pero los valores suaves, las búsquedas van a utilizar pares de igualdad y de valor clave serán de basura recogidas cuando la memoria Es ajustado.

+0

Pero no tengo un valor para asociar con la clave, por lo que la clave es lo único que se puede poner en una referencia suave. –

0

creo que esta clase se adapte a sus necesidades:

import java.util.*; 
import java.lang.ref.*; 

public class SoftSet<T> extends AbstractSet<T> { 

    private final WeakHashMap<T,SoftReference<T>> data = new WeakHashMap<T,SoftReference<T>>(); 

    public boolean add(T t) { 
    return null == data.put(t, new SoftReference<T>(t)); 
    } 

    public boolean remove(Object o) { 
    return null != data.remove(o); 
    } 

    public boolean contains(Object o) { 
    return data.containsKey(o); 
    } 

    public Iterator<T> iterator() { 
    return data.keySet().iterator(); 
    } 

    public int size() { 
    return data.size(); 
    } 

    public void clear() { 
    data.clear(); 
    } 

    public boolean removeAll(Collection<?> c) { 
    return data.keySet().removeAll(c); 
    } 

    public boolean retainAll(Collection<?> c) { 
    return data.keySet().retainAll(c); 
    } 
} 

La forma en que esto debería funcionar es que una vez que se elimina la referencia suave que es el valor, entonces el valor es débilmente accesible sólo y la clave se puede eliminar del mapa interno.

+0

Tal vez el downvote porque está envolviendo el objeto en dos referencias separadas de lo que necesita. Tener una sola subclase SoftReference con equals() igualdad en Google ConcurrentHashMap puede ser más clara de esta manera. –

1

Puesto que no hay ConcurrentHashSet usando referencias blandas, sólo hay dos enfoques:

1.) Su enfoque de la anulación de ConcurrentHashMap

  • equals y hashCode en el SoftReference
  • Dentro de equals y hashCode solo tienen acceso al objeto usando SoftReference#get
  • Pon SoftReference como clave, y cualquier objeto como valor (solo nulo no está permitido)
  • Si la referencia queda obsoleta al acceder hashCode o es igual, agregue la referencia a una cola de eliminación para eliminar frecuentemente las claves que están muertas.
  • Compruebe si contiene través containsKey

2.Utilice un ConcurrentMultimap<Integer, Set<SoftReference<RepLookupEntry>> y use hashCode como clave, y un conjunto sincronizado de SoftReferences como valores. Cuando obtiene un hashCode golpe, luego verifique el contenido de todos SoftReferences para la igualdad. No es muy bonito, estoy de acuerdo y difícil de sincronizar.

Si estuviera en su posición, no usaría SoftReferences en absoluto, sino un ConcurrentHashMap para mantener fuertes referencias a sus POJO. Cada vez que llega un nuevo elemento, también lo coloca en ConcurrentLinkQueue. Si la cola crece más allá de un límite determinado, comience a eliminar elementos de HashMap.

Cuestiones relacionadas