Ehcache - 使用List <Integer>作为缓存值

Gan*_*alf 7 java algorithm caching ehcache

所以这是我试图解决的问题 - 我有一个带有两个整数字段的对象我想要缓存

public class MyObject {
   int x;
   int y;
   ....
}
Run Code Online (Sandbox Code Playgroud)

现在该字段x是我主要匹配的 - 但是可能存在重复,在这种情况下我想要回到第二个字段(因此this.x = that.x和this.y = that.y).y只能是25个不同的值.现在我知道我可以将两者合并为String并将其用作缓存键,但是我必须尝试x+[25 possible values]确定它是否不在缓存中 - 使缓存未命中非常昂贵.我正在考虑尝试将a存储List<Integer>为字段的缓存值x,然后如果它们超过1,则迭代列表并查找匹配项y.

现在,如果我使用a ConcurrentList(或者如果我关心重复项,那么我们现在就忽略它)将多个线程能够添加到它,然后将其放回缓存而没有竞争条件?是否有可能Ehcache可能会将两个不同的列表对象返回到两个线程,然后当他们将新值添加到列表并尝试将其放回缓存时,我可能得到不确定的结果?您是否看到了构建此缓存的更好方法?

编辑:我很欣赏下面的答案,但每个人似乎都错过了重点.这会有用吗?Ehcache实际上可以为同一个cacheKey返回两个不同的对象(比如在调用期间对象是否在磁盘上并且它被序列化两次,每次调用一次).

Chr*_*her 5

您可以获得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();
}
Run Code Online (Sandbox Code Playgroud)

我在ehcache.xml中使用了以下内容:

<cache name="smallCache"
       maxElementsInMemory="1"
       eternal="true"
       overflowToDisk="true"
       diskPersistent="true"
       maxElementsOnDisk="200"
       memoryStoreEvictionPolicy="LRU"
       transactionalMode="off"
       >
</cache>
Run Code Online (Sandbox Code Playgroud)

一种解决方案可能是使用Explicit Locking,它似乎也适用于独立(非Terracotta)缓存(从ehcache 2.1开始).

另一种解决方案是只有一个可以修改List的线程.如果您有多个可以修改它的线程,并且您没有在缓存上使用锁定,那么您可以获得您描述的完全不确定的结果!