寻找简单的 Java 内存缓存

我正在寻找一个简单的 Java 内存缓存,它具有良好的并发性(所以 LinkedHashMap 不够好) ,并且可以定期序列化到磁盘。

我需要的一个特性是一种“窥视”对象的方法,但这已被证明是很难找到的。这意味着从缓存中检索一个对象,而不会导致缓存持有该对象的时间比其他情况下更长。

更新: 我没有提到的另一个需求是,我需要能够就地修改缓存的对象(它们包含浮点数组)。

Can anyone provide any recommendations?

260184 次浏览

这个怎么样: https://commons.apache.org/proper/commons-jcs/(更新到新地址,因为 JCS 现在在 Apache Commons 中)

Ehcache 是一个非常好的解决方案,并且有一种方法可以查看(安静是这种方法) ,这样它就不会更新空闲时间戳。在内部,Ehcache 是通过一组映射实现的,类似于 ConcurrentHashMap,因此它具有类似的并发优势。

尝试 Ehcache? 它允许您插入您自己的缓存到期算法,以便您可以控制您的偷看功能。

您可以序列化到磁盘、数据库、跨集群等。

如果你需要简单的东西,这个合适吗?

Map<K, V> myCache = Collections.synchronizedMap(new WeakHashMap<K, V>());

It wont save to disk, but you said you wanted simple...

相关网址:

(正如 Adam 评论的那样,同步地图对性能有很大影响。并不是说这个想法毫无根据,但是作为一个快速而肮脏的解决方案就足够了。)

Try this:

import java.util.*;


public class SimpleCacheManager {


private static SimpleCacheManager instance;
private static Object monitor = new Object();
private Map<String, Object> cache = Collections.synchronizedMap(new HashMap<String, Object>());


private SimpleCacheManager() {
}


public void put(String cacheKey, Object value) {
cache.put(cacheKey, value);
}


public Object get(String cacheKey) {
return cache.get(cacheKey);
}


public void clear(String cacheKey) {
cache.put(cacheKey, null);
}


public void clear() {
cache.clear();
}


public static SimpleCacheManager getInstance() {
if (instance == null) {
synchronized (monitor) {
if (instance == null) {
instance = new SimpleCacheManager();
}
}
}
return instance;
}


}

因为这个问题最初是问的,所以 Google's Guava library现在包含了一个强大而灵活的缓存。

您可以很容易地使用 Imcache

void example(){
Cache<Integer,Integer> cache = CacheBuilder.heapCache().
cacheLoader(new CacheLoader<Integer, Integer>() {
public Integer load(Integer key) {
return null;
}
}).capacity(10000).build();
}

内存中 Java 缓存的另一个选项是 Cache2k。 内存性能优于 EHCache 和谷歌番石榴,见 cache2k benchmarks page

使用模式与其他缓存类似,下面是一个例子:

Cache<String,String> cache = new Cache2kBuilder<String, String>() {}
.expireAfterWrite(5, TimeUnit.MINUTES)    // expire/refresh after 5 minutes
.resilienceDuration(30, TimeUnit.SECONDS) // cope with at most 30 seconds
// outage before propagating
// exceptions
.refreshAhead(true)                       // keep fresh when expiring
.loader(new CacheLoader<String, String>() {
@Override
public String load(final String key) throws Exception {
return ....;
}
})
.build();
String val = cache.peek("something");
cache.put("something", "hello");
val = cache.get("something");

If you have google guava as dependency then trying out guava cache, may be a good alternative.

试试 Jcabi 方面中的 @Cacheable。只需要一个注释,就可以将整个方法的结果缓存到内存中:

public class Resource {
@Cacheable(lifetime = 5, unit = TimeUnit.SECONDS)
public String load(URL url) {
return url.openConnection().getContent();
}
}

Also, read this article: http://www.yegor256.com/2014/08/03/cacheable-java-annotation.html