前段时间我使用软引用创建了一个缓存,但在尝试解决一个错误时,我开始担心实际上我做错了,它在不应该删除对象时删除了对象。这就是我的做法:
private static final Map<String, SoftReference<Buffered>> imageMap =
new HashMap<String,SoftReference<Buffered>>();
public static synchronized Buffered addImage(String sum, final byte[] imageData)
{
SoftReference<Buffered> bufferedRef = imageMap.get(sum);
Buffered buffered;
if (bufferedRef!=null)
{
//There are no longer any hard refs but we need again so add back in
if(bufferedRef.get()==null)
{
buffered = new Buffered(imageData, sum);
imageMap.put(sum, new SoftReference(buffered));
}
else
{
buffered=bufferedRef.get();
}
}
else
{
buffered = new Buffered(imageData, logDescriptor, sum);
imageMap.put(sum, new SoftReference(buffered));
}
return buffered;
}
public static Buffered getImage(String sum)
{
SoftReference<Buffered> sr = imageMap.get(sum);
if(sr!=null)
{
return sr.get();
}
return null;
}
所以这个想法是一个调用进程可以添加新的缓冲对象,这些对象可以通过键和来识别/查找,然后只要这个缓冲对象被至少一个对象使用,它就不会从地图中删除,但是如果它不再被任何对象使用,那么如果内存变得紧张,它可能是垃圾收集。
但是现在看我的代码很重要,关键字段总和总是在其他地方被引用(不一定是这种情况)
编辑:所以我尝试了 Colin 的解决方案,但我有点难过,因为 putIfAbsent() 似乎没有返回附加值。我修改了我的 addImage 方法以进行一些调试
public static synchronized Buffered addImage(String sum, final byte[] imageData)
{
Buffered buffered = new Buffered(imageData, sum);
Buffered buffered2 = imageMap.get(sum );
Buffered buffered3 = imageMap.putIfAbsent(sum,buffered );
Buffered buffered4 = imageMap.get(sum );
System.out.println("Buffered AddImage1:"+buffered);
System.out.println("Buffered AddImage2:"+buffered2);
System.out.println("Buffered AddImage3:"+buffered3);
System.out.println("Buffered AddImage4:"+buffered4);
return buffered2;
}
返回
Buffered AddImage1:com.Buffered@6ef725a6
Buffered AddImage2:null
Buffered AddImage3:null
Buffered AddImage4:com.Buffered@6ef725a6
所以它清楚地表明 Buffered 实例不是从那里开始的,并且已成功构建和添加,但肯定应该由 putIfAbsent 返回?