所以这是我试图解决的问题 – 我有一个带有两个整数字段的对象我想要缓存
public class MyObject {
int x;
int y;
....
}
现在字段x是我主要匹配的 – 但是可能存在重复,在这种情况下我想要回到第二个字段(因此this.x = that.x和this.y = that.y). y只能是25个不同的值.现在我知道我可以将两者合并为一个String并将其用作缓存键,但是我必须尝试x [25个可能的值]来实际确定它是否不在缓存中 – 使缓存未命中非常昂贵.我正在考虑尝试存储List< Integer>作为字段x的缓存值,然后如果它们超过1,则向下遍历列表并在y上查找匹配项.
现在,如果我使用ConcurrentList(或者如果我关心重复项,那么让我们暂时忽略它)将多个线程能够添加到它,然后将其放回缓存而没有竞争条件?是否有可能Ehcache可能会将两个不同的列表对象返回到两个线程,然后当他们将新值添加到列表并尝试将其放回缓存时,我可能得到不确定的结果?您是否看到了构建此缓存的更好方法?
编辑:我很欣赏下面的答案,但每个人似乎都错过了重点.这会有用吗? Ehcache实际上可以为同一个cacheKey返回两个不同的对象(比如在调用期间对象是否在磁盘上并且它被序列化两次,每次调用一次).
解决方法
您可以获得List(或任何Serializable)的两个不同实例!试试这个:
public static void main(final String[] args) throws Exception {
final Cache cache = CacheManager.getInstance().getCache("smallCache");
final List<String> list = new ArrayList<String>();
cache.put(new Element("A",list));
/* We put in a second element. Since maxElementsInMemory="1",this means
* that "A" will be evicted from memory and written to disk. */
cache.put(new Element("B",new ArrayList<String>()));
Thread.sleep(2000); // We need to wait a bit,until "A" is evicted.
/* Imagine,the following happens in Thread 1: */
final List<String> retrievedList1 =
(List<String>) cache.get("A").getValue();
retrievedList1.add("From Thread 1");
/* Meanwhile,someone puts something in the cache: */
cache.put(new Element("C",new ArrayList<String>()));
Thread.sleep(2000); // Once again,we wait a bit,until "A" is evicted.
/* Now the following happens in Thread 2: */
final List<String> retrievedList2 =
(List<String>) cache.get("A").getValue();
retrievedList2.add("From Thread 2");
cache.put(new Element("A",retrievedList2));
/* Meanwhile in Thread 1: */
cache.put(new Element("A",retrievedList1));
/* Now let's see the result: */
final List<String> resultingList =
(List<String>) cache.get("A").getValue();
for (final String string : resultingList) {
System.out.println(string);
} /* Prints only "From Thread 1". "From Thread 2" is lost.
But try it with maxElementsInMemory="3",too!! */
CacheManager.getInstance().shutdown();
}
我在ehcache.xml中使用了以下内容:
<cache name="smallCache"
maxElementsInMemory="1"
eternal="true"
overflowTodisk="true"
diskPersistent="true"
maxElementsOndisk="200"
memoryStoreevictionPolicy="LRU"
transactionalMode="off"
>
</cache>
一种解决方案可能是使用Explicit Locking,它似乎也可用于独立(非Terracotta)缓存(自ehcache 2.1起).
另一种解决方案是只有一个可以修改List的线程.如果您有多个可以修改它的线程,并且您没有在缓存上使用锁定,那么您可以获得您描述的完全不确定的结果!