我想使用MapMaker创建缓存大对象的映射,如果内存不足,应从缓存中删除这些大对象, 。 这个小演示程序似乎很好地工作:使用MapMaker创建缓存
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();
}
}
然而,当我做同样的事情在我的实际应用中,条目 基本上从缓存,尽快为他们添加删除。在我的真实 应用程序中,我也使用整数作为键,并且缓存值为 从包含某些数据的磁盘读取的归档块。据I 明白,只要不再使用 就会被垃圾收集垃圾收集,所以这似乎是有意义的,因为这些键是弱的 引用。如果我创建的地图是这样的:
data = new MapMaker()
.softValues()
.makeMap();
的条目是从来没有垃圾收集和我在测试程序得到了内存不足的错误 。 TestValue条目 上的finalize方法永远不会被调用。如果我改变了测试方法如下:
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) {
}
}
}
条目从缓存中,并在测试值 对象终结被称为删除,但过了一段时间我也得到一个内存不足, 错误。
所以我的问题是:什么是正确的方式来使用MapMaker创建一个 地图,可以用作缓存?为什么我的测试程序不能尽快删除 条目,如果我使用weakKeys?是否有可能将 添加引用队列到缓存映射?
有人可以编辑代码,使其更容易阅读? – nanda 2010-07-09 10:27:34
我对此有点惊讶。我已经使用'softValues'完全相同的方式,并且它工作正常,当内存不足时,SoftReference被清除。 – finnw 2010-07-17 00:27:33