【问题标题】:Looking for simple Java in-memory cache [closed]寻找简单的 Java 内存缓存 [关闭]
【发布时间】:2010-10-09 05:00:01
【问题描述】:

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

我需要但已证明很难找到的一个功能是一种“窥视”对象的方法。我的意思是从缓存中检索一个对象,而不会导致缓存保留该对象的时间比其他情况下更长。

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

任何人都可以提供任何建议吗?

【问题讨论】:

  • 我正在寻找类似的“正在处理中”且重量更轻的东西。我想用它在堆中的 Eclipse 插件中存储一些数据。 Ehcache 和 JCS 对我来说似乎过于重量级/分布式/J2EE。
  • 我会推荐 Apache Ignite(ignite.apache.org)
  • 这个问题已经结束(事实发生 6 年后),今天人们仍然想知道,这表明 SO 的主持人系统是如何失败的。

标签: java caching


【解决方案1】:

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

【讨论】:

  • 看起来@sanity 想要一个轻型缓存。
【解决方案2】:

Ehcache 是一个很好的解决方案,并且有一种方法可以窥视(getQuiet() 是方法),这样它就不会更新空闲时间戳。在内部,Ehcache 是用一组映射实现的,有点像 ConcurrentHashMap,因此它具有类似的并发优势。

【讨论】:

  • 谢谢,还有一个问题:如果我从 EHcache 中检索一个对象(比如一个数组)并修改它 - 缓存中的对象会更新吗? IE。 EHCache 是否维护对对象的引用?
  • 我相信是这样,但要安全地执行此操作,您当然必须适当地锁定对象。
  • 我喜欢 ehcache,但是,它是一个 10mb 的 jar。太大了。
【解决方案3】:

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

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

【讨论】:

    【解决方案4】:

    如果您需要一些简单的东西,这是否符合要求?

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

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

    链接:

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

    【讨论】:

    • 同步整个巨大的地图是一个巨大的惩罚。您可以轻松地将弱类型存储在并发哈希映射中并定期删除它们。
    • ConcurrentHashMap 优于 Collections.synchronizedMap stackoverflow.com/questions/6692008/…
    • 性能方面,ConcurrentHashMap 绝对性能更好,但在允许垃圾收集器回收内存方面,它不共享 WeakHashMap 的属性。这对您可能很重要,也可能不重要。
    • 然后使用ConcurrentHashMap&lt;WeakReference&lt;T&gt;&gt;docs.oracle.com/javase/7/docs/api/java/lang/ref/…
    【解决方案5】:

    试试这个:

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

    【讨论】:

    • 依赖同步地图的问题已经在其他答案中讨论过了。
    • @sergeyB :我正在寻找一个类似的解决方案,它可以简单地实现缓存...谢谢
    • public static SimpleCacheManager getInstance() { 应该是 public synchronized static SimpleCacheManager getInstance() { 否则 if (instance == null) { 不是线程安全的。在这种情况下,您可以一起删除监控对象,因为所有 getInstance() 调用都会发生同步,请参阅:javaworld.com/article/2073352/core-java/…
    • 我可以推荐对单例使用枚举吗? dzone.com/articles/java-singletons-using-enum
    【解决方案6】:

    自从最初提出这个问题以来,Google's Guava library 现在包含一个强大而灵活的缓存。我会推荐使用这个。

    【讨论】:

    • 请注意 Spring 不再支持 Guava 缓存:stackoverflow.com/questions/44175085/…
    • @sanity 是否实现了 Jcache?
    • Caffine 也是一个不错的高性能缓存库。 Caffeine 是基于 Java 8 的高性能、近乎最佳的缓存库。Caffeine 使用受 Google Guava 启发的 API 提供内存缓存
    【解决方案7】:

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

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

    【讨论】:

      【解决方案8】:

      内存中 Java 缓存的另一个选项是 cache2k。 内存性能优于 EHCache 和 google guava,见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");
      

      如果您有 google guava 作为依赖项,那么尝试 guava 缓存可能是一个不错的选择。

      【讨论】:

      • cruftex,如果我关闭我的应用程序,缓存是否会销毁所有注册的数据?
      【解决方案9】:

      jcabi-aspects 尝试@Cacheable。使用单个注释,您可以使整个方法结果可缓存在内存中:

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

      另外,请阅读这篇文章:http://www.yegor256.com/2014/08/03/cacheable-java-annotation.html

      【讨论】:

        猜你喜欢
        • 2012-07-10
        • 2013-01-12
        • 2011-04-24
        • 1970-01-01
        • 2017-05-31
        • 1970-01-01
        • 1970-01-01
        • 2012-10-20
        相关资源
        最近更新 更多