web-dev-qa-db-ja.com

シンプルなJavaメモリ内キャッシュを探しています

同時実行性が良好で(したがってLinkedHashMapでは十分ではない)、定期的にディスクにシリアル化できるシンプルなJavaメモリ内キャッシュを探しています。

必要な機能の1つですが、見つけるのが難しいことがわかっている機能は、オブジェクトを「覗く」方法です。これは、キャッシュが他の方法で保持するよりも長くオブジェクトを保持することなく、キャッシュからオブジェクトを取得することを意味します。

更新:私が言及しなかった追加の要件は、キャッシュされたオブジェクト(フロート配列を含む)をその場で変更できる必要があるということです。

誰でも推奨事項を提供できますか?

90
sanity

この質問はもともと質問されていたため、 GoogleのGuavaライブラリ には強力で柔軟なキャッシュが含まれています。これを使用することをお勧めします。

53
sanity

Ehcache はこのための非常に優れたソリューションであり、アイドルタイムスタンプを更新しないように覗く方法があります( getQuiet() がメソッドです)。内部的には、EhcacheはConcurrentHashMapのようなマップのセットで実装されているため、同様の並行処理の利点があります。

36
Alex Miller

シンプルなものが必要な場合、これは法案に適合しますか?

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

それはディスクに保存しませんが、あなたはシンプルにしたいと言いました...

リンク:

(Adamがコメントしたように、マップの同期はパフォーマンスに影響を与えます。アイデアに髪の毛がないと言っているわけではありませんが、迅速で汚い解決策としては十分です。)

19
Evan

インメモリJavaキャッシュの別のオプションは cache2k です。メモリ内のパフォーマンスは、EHCacheおよびgoogle guavaよりも優れています。 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");

依存関係としてgoogle guavaを使用している場合は、guavaキャッシュを試してみるとよいでしょう。

15
cruftex

imcache を簡単に使用できます。サンプルコードは次のとおりです。

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

@Cacheable from jcabi-aspects を試してください。単一の注釈で、メソッド全体の結果をメモリにキャッシュ可能にします。

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

8
yegor256

これを試して:

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

}
8

これはどうですか: https://commons.Apache.org/proper/commons-jcs/ (JCSは現在Apache Commonsにあるため、新しいアドレスに更新されました)

3
TofuBeer

Ehcache ?を試してください独自のキャッシュ有効期限アルゴリズムをプラグインできるため、ピーク機能を制御できます。

クラスター全体でディスク、データベースにシリアル化できます...

0
Stephen