所以这是我试图解决的问题 – 我有一个带有两个整数字段的对象我想要缓存
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的线程.如果您有多个可以修改它的线程,并且您没有在缓存上使用锁定,那么您可以获得您描述的完全不确定的结果!