轻量级Java对象缓存API


99

我正在寻找Java内存对象缓存API。有什么建议吗?您过去使用过什么解决方案?

当前

现在,我只是在使用地图:

Map cache = new HashMap<String, Object>();
cache.put("key", value);

要求

我需要扩展缓存以包括以下基本功能:

  • 最大尺寸
  • 生存时间

但是,我不需要更复杂的功能,例如:

  • 来自多个进程的访问(缓存服务器)
  • 持久性(到磁盘)

意见建议

内存中缓存:

  • Guava CacheBuilder-活动开发。请参阅此演示文稿
  • LRUMap-通过API配置。没有TTL。并非专门用于缓存。
  • whirlycache -XML配置。邮件列表。上次更新时间:2006年。
  • cache4j -XML配置。俄语文档。上次更新时间:2006年。

企业缓存:

  • JCS-属性配置。广泛的文档。
  • Ehcache -XML配置。广泛的文档。到目前为止,根据Google的点击量最受欢迎。

3
您可以编辑“建议内存中缓存”部分以包含Guava缓存吗?我一直在寻找像您一样的轻量级缓存机制,但发现了这个问题,但没有找到Guava,因为它已经降级了。现在,我使用了番石榴缓存程序包,这真是令人惊讶。
Andras

1
做完了 :-)很高兴您喜欢它!
凯文·布瑞里恩

也许您还想考虑添加相对较新的cache2k。在他们的基准网页上,据说它的性能比ehcache和Guava好得多。
user3001 2014年

Answers:


57

EHCache非常好。您可以创建一个内存缓存。查看他们的代码示例,以获取创建内存中缓存的示例。您可以指定最大大小和生存时间。

EHCache确实提供了一些高级功能,但是如果您对使用它们不感兴趣,那就不要。但是很高兴知道,如果您的需求发生变化,它们就会在那里。

这是内存中的缓存。用代码创建,没有配置文件。

CacheManager cacheManager = CacheManager.getInstance();
int oneDay = 24 * 60 * 60;
Cache memoryOnlyCache = new Cache("name", 200, false, false, oneDay, oneDay);
cacheManager.addCache(memoryOnlyCache);

创建一个可容纳200个元素且ttl为24小时的缓存。


2
EHCache是​​仅引用对象还是对其进行序列化然后反序列化?
PHUONG阮

2
EHCache是​​重量级解决方案吗?我们正在研究现有的缓存解决方案,以在Android上实现API缓存。
马提亚斯(Matthias)2010年

2
对于Android来说太重了。我正在使用Kitty缓存,它是如此完美!
费利佩

@Stevet K,我现在不知道这种缓存技术,但是我猜想getInstance()已被删除或更改。
Menai Ala Eddine-阿拉丁

46

我真的很喜欢Google GuavaAPIMapMaker附带的

JavaDoc有一个非常简洁的示例,展示了其易用性和强大功能:

ConcurrentMap<Key, Graph> graphs = new MapMaker()
   .concurrencyLevel(32)
   .softKeys()
   .weakValues()
   .expiration(30, TimeUnit.MINUTES)
   .makeComputingMap(
       new Function<Key, Graph>() {
         public Graph apply(Key key) {
           return createExpensiveGraph(key);
         }
       });

此外,Guava的10.0版引入了更广泛的com.google.common.cache软件包有关如何使用它们的一个不错的Wiki条目)。



@mxttie:谢谢,我已经添加了链接,可以建议对这种添加进行编辑。
约阿希姆·绍尔

10

您还可以在以下位置签出我名为KittyCache的小型缓存库:

https://github.com/treeder/kitty-cache

有一些性能基准与ehcache。

它在SimpleJPA项目中用作二级缓存。


1
不错,但只要它有TTL。
Rosdi Kasim 2011年

谢谢 !只是在我想检查是否有人已经开源之前输入的代码:)
jpillora 2012年

@RosdiKasim实际上在put()调用上确实具有TTL,例如:cache.put(“ mykey”,value,500); 500是TTL。
特拉维斯·里德

1
@TravisR好吧...,那时候还没有TTL ..:p
Rosdi Kasim 2012年

啊,没有意识到那条评论是多久以前的。
特拉维斯·里德

9

您可以签出LinkedHashMap来实现没有第三方jar的简单缓存:

    Map <String, Foo> cache = new LinkedHashMap<String, Foo>(MAX_ENTRIES + 1, .75F, true) {

        public boolean removeEldestEntry(Map.Entry<String, Foo> eldest) {
            return size() > MAX_ENTRIES;
        }
    };

那么你可以像这样从缓存中获取

    Foo foo = cache.get(key);
    if (foo == null && !cache.containsKey(key)) {
        try {
            FooDAO fooDAO = DAOFactory.getFooDAO(conn);
            foo = fooDAO.getFooByKey(key);
            cache.put(key, foo);
        } catch (SQLException sqle) {
            logger.error("[getFoo] SQL Exception when accessing Foo", sqle);
        }
    }

剩下的作为练习留给读者:)


2
我认为这种方法没有TTL容量。不过,这将是朝着自己的方向迈进的良好开端。
Chase Seibert

是的,在阅读器练习:p中,我将保留TTL内容,而且当然,第三方库的测试远远超过滚动您自己的库。
JeeBee


5

JCS久经考验。即使就缓存机制而言,它还是很轻巧的,但是您仍可以深入研究实际的代码,并在幕后模仿它们对HashMap所做的事情,以精确地满足您的需要,而不再需要更多。您似乎对所要查找的东西有一个很好的主意。


我认为您的意思是,就缓存机制而言,这还不算很轻松?但是,它似乎是最受欢迎的企业解决方案之一。
Chase Seibert

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.