Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/326.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 使用番石榴的理想缓存_Java_Caching_Guava_Canonicalization - Fatal编程技术网

Java 使用番石榴的理想缓存

Java 使用番石榴的理想缓存,java,caching,guava,canonicalization,Java,Caching,Guava,Canonicalization,在过去的几周里,我断断续续地试图用guava的方法找到理想的缓存实现。请看我前面的两个问题,并遵循我的思考过程 根据我所学到的,我的下一个尝试是放弃软值,转而支持maximumSize和expireAfterAccess: ConcurrentMap<String, MyObject> cache = new MapMaker() .maximumSize(MAXIMUM_SIZE) .expireAfterAccess(MINUTES_TO_EXPI

在过去的几周里,我断断续续地试图用guava的方法找到理想的缓存实现。请看我前面的两个问题,并遵循我的思考过程

根据我所学到的,我的下一个尝试是放弃软值,转而支持maximumSize和expireAfterAccess:

ConcurrentMap<String, MyObject> cache = new MapMaker()
        .maximumSize(MAXIMUM_SIZE)
        .expireAfterAccess(MINUTES_TO_EXPIRY, TimeUnit.MINUTES)
        .makeComputingMap(loadFunction);
ConcurrentMap cache=newmapmaker()
.最大尺寸(最大尺寸)
.expireAfterAccess(分钟到分钟到期,时间单位:分钟)
.makeComputingMap(加载函数);
在哪里

Function loadFunction=新函数(){
@凌驾
公共MyObject应用(字符串uidKey){
返回getFromDataBase(uidKey);
}
};
然而,我仍然要解决的一个问题是,一旦对象的时间到了,这个实现将逐出对象,即使它们是强可访问的。这可能会导致环境中有多个具有相同UID的对象浮动,这是我不想要的(我相信我试图实现的就是所谓的规范化)

因此,就我所知,唯一的答案是有一个额外的映射,它作为一个interner,我可以检查数据对象是否仍在内存中:

ConcurrentMap<String, MyObject> interner = new MapMaker()
        .weakValues()
        .makeMap();
ConcurrentMap interner=newmapmaker()
.weakValues()
.makeMap();
荷载函数将进行修改:

Function<String, MyObject> loadFunction = new Function<String, MyObject>() {
   @Override
   public MyObject apply(String uidKey) {
      MyObject dataObject = interner.get(uidKey);
      if (dataObject == null) {
         dataObject = getFromDataBase(uidKey);
         interner.put(uidKey, dataObject);
      }
      return dataObject;
   }
};
Function loadFunction=新函数(){
@凌驾
公共MyObject应用(字符串uidKey){
MyObject数据对象=interner.get(uidKey);
if(dataObject==null){
dataObject=getFromDataBase(uidKey);
interner.put(uidKey,dataObject);
}
返回数据对象;
}
};

但是,在缓存中使用两个映射而不是一个映射似乎效率低下。有没有更复杂的方法来解决这个问题?一般来说,我这样做是正确的,还是应该重新考虑我的缓存策略?

两个映射是否有效完全取决于getFromDatabase()的价格和对象的大小。这样做似乎并不超出所有合理的界限

至于实现,看起来您可能可以以稍微不同的方式分层映射,以获得所需的行为,并且仍然具有良好的并发属性

  • 使用弱值创建第一个映射,并将计算函数getFromDatabase()放在此映射上
  • 第二个映射是即将到期的映射,也是正在计算的映射,但是这个函数只是从第一个映射得到的
  • 通过第二张地图进行所有访问

    换句话说,过期映射的作用是将最近使用的对象子集固定在内存中,而弱引用映射是真正的缓存


    -dg

    我不明白这里的全部情况,但有两件事

  • 给出这样一句话:“这个实现将逐出对象,即使它们是强可访问的,一旦它们的时间到了。这可能会导致多个具有相同UID的对象在环境中浮动,这是我不想要的。”--听起来你只需要使用weakKeys(),而不需要使用定时或基于大小的逐出

  • 或者,如果你真的想把一个“实习生”带到这里面,我会用一个真正的
    Interners.newWeakInterner


  • +1谢谢,你说得对,loadFunction添加的逻辑正在做“interner”映射作为第二个计算映射所能做的事情。我认为这主要是一个装饰性的区别,因为“interner”映射只能通过即将到期的映射(已经在处理并发请求)访问,但更优雅。您的答案似乎支持我的做法-在接受输入之前,我要看看是否还有其他建议-我想我不完全理解使用weakKeys(),特别是如果键是String或UUID等。那么我是否需要一个包装器类作为键?此外,我还没有掌握使用弱键和抛弃基于时间和大小的驱逐的策略。我确实希望在访问后至少x分钟内保持缓存对象的强可访问性(或者我不希望?)。我的问题是,如果对象仍然碰巧处于长时间运行的进程中,那么之后会发生什么。可能是我遗漏了一些关于弱键的信息。关于“interner”-我考虑使用一个真正的interner,但是它只支持intern()方法,并且无法检查对象是否真的在其中。弱映射使我能够知道对象是否在内存中,或者是否需要加载。也许我用这个词太随便了?嘿,凯文,我接受达伦的回答,但如果你有机会的话,我希望你能澄清一下weakKeys()。谢谢虽然有点晚了,但您可能仍然有兴趣了解制作缓存的每个不同选项的内存成本:@DimitrisAndreou-非常有趣,感谢链接!一旦我开始更多地使用它们,我计划为
    Cache
    /
    CacheBuilder
    更新这篇文章。
    Function<String, MyObject> loadFunction = new Function<String, MyObject>() {
       @Override
       public MyObject apply(String uidKey) {
          MyObject dataObject = interner.get(uidKey);
          if (dataObject == null) {
             dataObject = getFromDataBase(uidKey);
             interner.put(uidKey, dataObject);
          }
          return dataObject;
       }
    };