具有弱值的哈希映射

2022-09-01 17:09:33

我正在为永久存储的对象实现缓存。这个想法是:

  • 方法getObjectFromPersistence(long id); ///Takes about 3 seconds
  • 方法getObjectFromCache(long id) //Instantly

并有一个方法:使用以下伪代码:getObject(long id)

synchronized(this){
    CustomObject result= getObjectFromCache(id)
    if (result==null){
       result=getObjectFromPersistence(id);
       addToCache(result);
    }
    return result;
}

但是我需要允许垃圾回收器收集自定义对象。到目前为止,我一直在使用一个来实现。问题是,随着时间的推移,哈希映射变得充满空的。HashMap<Long,WeakReference<CustomObject>WeakReferences

我已经检查了WeakHashMap,但那里的键很弱(并且值仍然是强引用),因此使用弱引用进行长交是没有意义的。

解决此问题的最佳解决方案是什么?有没有一些“逆弱哈希图”或类似的东西?

谢谢


答案 1

您可以使用番石榴地图制作器

ConcurrentMap<Long, CustomObject> graphs = new MapMaker()
   .weakValues()
   .makeMap();

您甚至可以通过替换为以下内容来包含计算部分:makeMap()

   .makeComputingMap(
       new Function<Long, CustomObject>() {
         public CustomObject apply(Long id) {
           return getObjectFromPersistence(id);
         }
       });

由于您正在编写的内容看起来很像缓存,因此更新,更专业的缓存(通过CacheBuilder构建)可能与您更相关。它不直接实现接口,但提供了更多您可能希望用于缓存的控件。Map

您可以参考此内容以获取有关如何使用CacheBuilder的详细信息,以下是快速访问的示例:

LoadingCache<Integer, String> cache = CacheBuilder.newBuilder()
   .maximumSize(100)
   .expireAfterWrite(10, TimeUnit.MINUTES)
   .build(
       new CacheLoader<Integer, String>() {
           @Override
           public String load(Integer id) throws Exception {
               return "value";
           }
       }
   ); 

答案 2

A 被添加到其在收集其引用的构造时提供的 ReferenceQueue 中。WeakReference

您可以在访问缓存时,并按住 a 以了解如果在队列中找到引用,要删除哪个条目。pollReferenceQueueHashMap<WeakReference<CustomObject>,Long>

或者,如果缓存不经常使用,则可以在单独的线程中监视队列