quiero utilizar Map Maker para crear un mapa que almacena en caché los objetos de gran tamaño, que debe ser eliminado de la caché si no hay suficiente memoria. Este pequeño programa de demostración parece funcionar bien:El uso de Map Maker para crear una memoria caché
public class TestValue {
private final int id;
private final int[] data = new int[100000];
public TestValue(int id) {
this.id = id;
}
@Override
protected void finalize() throws Throwable {
super.finalize();
System.out.println("finalized");
}
}
public class Main {
private ConcurrentMap<Integer, TestValue> cache;
MemoryMXBean memoryBean;
public Main() {
cache = new MapMaker()
.weakKeys()
.softValues()
.makeMap();
memoryBean = ManagementFactory.getMemoryMXBean();
}
public void test() {
int i = 0;
while (true) {
System.out.println("Etntries: " + cache.size() + " heap: "
+ memoryBean.getHeapMemoryUsage() + " non-heap: "
+ memoryBean.getNonHeapMemoryUsage());
for (int j = 0; j < 10; j++) {
i++;
TestValue t = new TestValue(i);
cache.put(i, t);
}
try {
Thread.sleep(100);
} catch (InterruptedException ex) {
}
}
}
/**
* @param args the command line arguments
*/
public static void main(String[] args) {
Main m = new Main();
m.test();
}
}
Sin embargo, cuando lo haga lo mismo en mi aplicación real, las entradas son básicamente eliminado de la caché tan pronto como se abonen. En mi aplicación real , también utilizo como teclas de números enteros, y los valores son almacenados en caché de archivos bloques leídos del disco que contiene algunos datos. Por lo que yo entiendo , débiles son las referencias recolección de basura tan pronto como estén ya no se usa, así que esto parece tener sentido ya que las claves son débiles referencias. Si creo el mapa de esta manera:
data = new MapMaker()
.softValues()
.makeMap();
Las entradas son no recolección de basura y me sale un error de falta de memoria en mi programa de prueba. El método de finalización en las entradas TestValue nunca se llama. Si cambio el método de ensayo a lo siguiente:
public void test() {
int i = 0;
while (true) {
for (final Entry<Integer, TestValue> entry :
data.entrySet()) {
if (entry.getValue() == null) {
data.remove(entry.getKey());
}
}
System.out.println("Etntries: " + data.size() + " heap: "
+ memoryBean.getHeapMemoryUsage() + " non-heap: "
+ memoryBean.getNonHeapMemoryUsage());
for (int j = 0; j < 10; j++) {
i++;
TestValue t = new TestValue(i);
data.put(i, t);
}
try {
Thread.sleep(100);
} catch (InterruptedException ex) {
}
}
}
entradas se eliminan de la memoria caché y el finalizador de los TestValue objetos que se llama, pero después de un tiempo también reciben un out-of-memoria de errores .
Así que mi pregunta es: ¿cuál es la forma correcta de utilizar MapMaker para crear un mapa que se puede utilizar como un caché? ¿Por qué mi programa de prueba no elimina las entradas lo antes posible si uso weakKeys? ¿Es posible agregar una cola de referencia al mapa de caché?
alguien puede editar el código para que sea más fácil de leer? – nanda
Estoy un poco sorprendido por esto. He usado 'softValues' exactamente de la misma manera y funcionó bien, con el' SoftReference's borrado cuando la memoria se agota. – finnw