gpt4 book ai didi

guava - 使用 MapMaker 创建缓存

转载 作者:行者123 更新时间:2023-12-04 06:49:21 31 4
gpt4 key购买 nike

我想使用 MapMaker 创建一个缓存大对象的 map ,
如果没有足够的内存,应该从缓存中删除它。
这个小演示程序似乎工作正常:

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();
}

}

但是,当我在实际应用程序中做同样的事情时,条目是
基本上一添加就从缓存中删除。在我的真实
应用程序,我也使用整数作为键,缓存的值是
从包含一些数据的磁盘读取的归档块。就我而言
理解,弱引用一出现就会被垃圾收集
不再使用,所以这似乎是有道理的,因为键很弱
引用。如果我像这样创建 map :
    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) {
}
}
}

条目从缓存和 TestValue 上的终结器中删除
对象被调用,但一段时间后我也出现内存不足
错误。

所以我的问题是:使用 MapMaker 创建一个的正确方法是什么?
可以用作缓存的 map ?为什么我的测试程序没有删除
如果我使用weakKeys,尽快输入条目?是否有可能
将引用队列添加到缓存映射?

最佳答案

有很多事情可能会发生,但是对于使用软值的测试程序:即使您有尚未被垃圾收集的 SoftReferences,您也​​可能得到 OutOfMemoryError。值得重申的是:即使您有尚未清除的 SoftReferences,您也​​可能会收到 OutOfMemoryError。

SoftReferences 有点奇怪,见 http://jeremymanson.blogspot.com/2009/07/how-hotspot-decides-to-clear_07.html用于描述当前力学。很可能在您的测试用例中,GC 只是没有时间进行两次完整的 GC。

当您使用弱键时,CG 会立即清除它们,而不必等待完整的 GC 暂停。 (b/c WeakReferences 被积极收集。)

在我看来,如果你想要一个带有 Integer 键的内存敏感缓存,我认为以下是合适的:

data = new MapMaker().softValues().makeMap();

您可以轻松制作一个抛出 OutOfMemoryError 的测试程序,但如果您的实际应用程序表现良好,并且不会承受太大压力,那么您可能没问题。 SoftReferences 很难做到正确。

如果您需要使用 System.gc() 避免内存不足,我建议您切换到具有固定最大大小的 LRU 映射(例如,请参阅 java.util.LinkedHashMap 的 javadoc。)它不是并发的,但我希望它最终会为您提供更好的吞吐量,而不是要求系统多次进行完全暂停的垃圾收集。

哦,还有关于整数键和 weakKeys() 的最后一点:MapMaker 在使用弱键或软键时对键使用身份比较,这很难正确执行。见证以下几点:
Map<Integer,String> map = new MapMaker().weakKeys().makeMap();
Integer a = new Integer(1);
Integer b = new Integer(1);
Integer c = 1; //auto box
Integer d = 1; //auto box
map.put(a, "A");
map.put(b, "B");
map.put(c,"C");
map.put(d,"D");
map.size() // size is 3;

祝你好运。

关于guava - 使用 MapMaker 创建缓存,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3210606/

31 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com