13

我有一个想要保持打开许多文件的应用程序:它定期收到一个客户端请求,说“向文件 X 添加一些数据”,并且该文件已经打开并且文件的标题部分已经解析是理想的,这样这篇写得很快。但是,保持打开这么多文件对操作系统来说并不是很好,如果我们的数据存储需求增长,这可能变得不可能。

所以我想要一个“给我这个文件句柄,如果它没有缓存就打开”功能,以及一些自动关闭没有被写入的文件的过程,比如五分钟。对于在短时间内写入的缓存文件句柄的特定情况,这可能就足够了,但这似乎是一个足够普遍的问题,应该有诸如“如果可能的话,从缓存中给我名为 X 的对象”和“我现在已经完成了对象 X,所以从现在起五分钟后让它有资格被驱逐”。

core.cache看起来可能适合此目的,但是文档非常缺乏,并且 源代码 没有提供有关如何使用它的特别线索。它的 TTLCache 看起来很有前途,但不清楚如何使用它依赖于垃圾收集来驱逐项目,所以当我准备让资源过期时,我无法干净地关闭它。

当然,我可以自己动手,但是有很多棘手的地方,我确信我会得到一些微妙的错误,所以我希望有人能指出我的这个功能的实现。我的代码在 clojure 中,但是如果可以找到最好的实现,当然使用 java 库会非常好。

4

2 回答 2

6

查看Guava 的缓存实现

  • 您可以为“如果句柄被缓存,则返回它,否则打​​开,缓存并返回它”语义的方法提供一个Callable(或一个CacheLoaderget
  • 您可以配置定时驱逐,例如expireAfterAccess
  • 您可以注册一个RemovalListener以在删除时关闭句柄

稍微修改链接的 Guava 页面中的代码示例,使用CacheLoader

LoadingCache<Key, Handle> graphs = CacheBuilder.newBuilder()
   .maximumSize(100) // sensible value for open handles?
   .expireAfterAccess(5, TimeUnit.MINUTES)
   .removalListener(removalListener)
   .build(
       new CacheLoader<Key, Handle>() {
         public Handle load(Key key) throws AnyException {
           return openHandle(key);
         }
       });

RemovalListener<Key, Handle> removalListener = 
  new RemovalListener<Key, Handle>() {
    public void onRemoval(RemovalNotification<Key, Handle> removal) {
      Handle h = removal.getValue();
      h.close(); // tear down properly
    }
  };

* 免责声明 *我自己没有以这种方式使用过缓存,请确保您对此进行了明智的测试。

于 2013-02-12T22:30:24.600 回答
1

如果您不介意一些 java,请参阅http://ehcache.org/http://ehcache.org/apidocs/net/sf/ehcache/event/CacheEventListener.html

于 2013-02-12T22:31:38.307 回答