加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 编程开发 > Java > 正文

java – Ehcache – 使用List作为缓存值

发布时间:2020-12-14 06:02:52 所属栏目:Java 来源:网络整理
导读:所以这是我试图解决的问题 – 我有一个带有两个整数字段的对象我想要缓存 public class MyObject { int x; int y; ....} 现在字段x是我主要匹配的 – 但是可能存在重复,在这种情况下我想要回到第二个字段(因此this.x = that.x和this.y = that.y). y只能是25
所以这是我试图解决的问题 – 我有一个带有两个整数字段的对象我想要缓存
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的线程.如果您有多个可以修改它的线程,并且您没有在缓存上使用锁定,那么您可以获得您描述的完全不确定的结果!

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读