寻找简单的Java内存缓存


102

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

我需要但很难找到的一个功能是一种“窥视”对象的方法。我的意思是从缓存中检索对象,而不会导致缓存对对象的保留时间超过其应有的保留时间。

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

谁能提供任何建议?


1
我正在寻找“在过程中”并且重量更轻的类似物品。我想用它在堆中的Eclipse插件中存储一些数据。就我的口味而言,Ehcache和JCS似乎过于笨重/分布式/ J2EE。
Uri


我会推荐Apache Ignite(ignite.apache.org
Bhagat S.

1
这个问题已经解决了(事实已经过去了6年),而今天仍然有人想知道,这表明SO的主持人系统是如何失败的。
dustinevan

Answers:



37

Ehcache是一个很好的解决方案,它有一个偷看的方法(getQuiet()是方法),这样它就不会更新空闲时间戳。在内部,Ehcache是​​通过一组映射实现的,类似于ConcurrentHashMap,因此它具有类似的并发优势。


2
谢谢,还有一个问题:如果我从EHcache中检索一个对象(例如数组),并对其进行修改-该对象是否会在缓存中更新?即。是EHCache维护对对象的引用吗?
健全性,

1
我相信,但是为了安全地进行此操作,您当然必须适当地锁定该对象。
亚历克斯·米勒

我喜欢ehcache,但是它是一个10mb的jar。太大了
markthegrea

23

如果您需要简单的东西,这是否合算?

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

它不会保存到磁盘,但是您说过想要简单...

链接:

(正如亚当(Adam)所说,同步地图会降低性能。不是说这个想法没有毛病,但足以作为一种快速而肮脏的解决方案。)


4
同步整个巨型地图是一项沉重的代价。您可以轻松地将弱类型存储在并发哈希图中,并定期删除它们。
亚当·根特

7
ConcurrentHashMap的比Collections.synchronizedMap更好stackoverflow.com/questions/6692008/...
巴勃罗·莫雷蒂

8
从性能角度来看,ConcurrentHashMap绝对性能更好,但是就允许垃圾收集器回收内存而言,它没有共享WeakHashMap的属性。这对您可能不重要。
伊万(Evan)

4
然后使用ConcurrentHashMap<WeakReference<T>>docs.oracle.com/javase/7/docs/api/java/lang/ref/…–
jdmichal

19

内存中Java缓存的另一个选项是cache2k。内存性能优于EHCache和google番石榴,请参阅cache2k基准测试页面

使用模式类似于其他缓存。这是一个例子:

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");

如果您将谷歌番石榴作为依赖项,那么尝试番石榴缓存可能是一个不错的选择。


cruftex,如果我关闭我的应用程序,缓存将销毁所有注册的数据或否?
Menai Ala Eddine-阿拉丁

10

您可以轻松使用imcache。下面是示例代码。

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

9

试试这个:

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;
    }

}

在其他答案中已经讨论了依赖同步映射的问题。
2013年

@sergeyB:我一直在寻找一种类似的解决方案,该解决方案易于实现缓存...谢谢
Prakruti Pathik,2015年

1
public static SimpleCacheManager getInstance() {应当public synchronized static SimpleCacheManager getInstance() {否则if (instance == null) {不是线程安全的。在这种情况下,你可以删除监控对象的所有在一起,因为同步发生的所有的getInstance()调用,请参阅:javaworld.com/article/2073352/core-java/...
灿Kavaklıoğlu

我可以建议对单例使用枚举吗?dzone.com/articles/java-singletons-using-enum
Erk



0

尝试Ehcache吗?它允许您插入自己的缓存过期算法,以便您可以控制监视功能。

您可以序列化到磁盘,数据库,整个集群等...

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.