2008-10-22 8 views
52

구현하기가 쉽지만 이미 존재하는 것을 재사용하고 싶습니다.Java에서 LRU 캐시를 사용하기 쉽고 간단합니다.

문제 다른 페이지, 역할에 대한 구성을 XML에서로드하므로 입력의 조합이 상당히 증가 할 수 있다는 점을 해결하고 싶습니다 (그러나 99 %에서는 그렇지 않습니다) . 이 1 %를 처리하기 위해 캐시에있는 항목의 최대 개수를 갖고 싶습니다 ...

아파치 공유지에서 org.apache.commons.collections.map.LRUMap을 찾았지만 괜찮아 보이기를 원합니다. 또한 다른 것을 확인하십시오. 어떤 추천?

+0

@Suporwski 어떻게 문제를 해결 했습니까? – Hunt

+0

@Hunt 나는 커먼즈로부터 LRUMap을 가지고있다 – Juraj

+0

매우 유사한 질문 [여기] (http://stackoverflow.com/q/221525/2032064) – Mifeet

답변

87

당신은 LinkedHashMap (자바 1.4 이상)를 사용할 수 있습니다 :

// Create cache 
final int MAX_ENTRIES = 100; 
Map cache = new LinkedHashMap(MAX_ENTRIES+1, .75F, true) { 
    // This method is called just after a new entry has been added 
    public boolean removeEldestEntry(Map.Entry eldest) { 
     return size() > MAX_ENTRIES; 
    } 
}; 

// Add to cache 
Object key = "key"; 
cache.put(key, object); 

// Get object 
Object o = cache.get(key); 
if (o == null && !cache.containsKey(key)) { 
    // Object not in cache. If null is not a possible value in the cache, 
    // the call to cache.contains(key) is not needed 
} 

// If the cache is to be used by multiple threads, 
// the cache must be wrapped with code to synchronize the methods 
cache = (Map)Collections.synchronizedMap(cache); 
+5

커먼즈 콜렉션의 LRUMap 또한 좋은 선택이다. –

+1

좋아요, 그래서 LRUMap을 사용하기로 결정했습니다. – Juraj

+0

참고 - 두 링크가 모두 같은 예제로 이동합니다. 이전 버전은 LHM javadoc이어야합니다. – JeeBee

21

이 오래된 질문이지만, 후손을 위해 내가 LRUMap 달리, 스레드 안전 인 ConcurrentLinkedHashMap를 나열하고 싶었다. 사용법은 매우 간단합니다 :

ConcurrentMap<K, V> cache = new ConcurrentLinkedHashMap.Builder<K, V>() 
    .maximumWeightedCapacity(1000) 
    .build(); 

그리고 문서는 LRU 캐시 크기 기반 대신 숫자 -의 - 항목 기반의 만드는 방법 같은 좋은 examples을 가지고 있습니다.

+5

[Caffeine] (https://github.com/ben-manes/caffeine)은 Java 8 재 작성으로 [더 빠름] (https://github.com/ben-manes/caffeine/wiki/Benchmarks)과 더 많은 [기능] (https://github.com/ben-manes/caffeine/wiki/Cache)을 제공합니다. –

1

나는 또한 동일한 문제가 있었고 어떤 좋은 라이브러리도 찾지 못했습니다 ... 그래서 내 자신을 만들었습니다.

simplelrucache는 TTL을 지원하는 스레드 세이프, 매우 단순한 비 분산 LRU 캐싱을 제공합니다. 그것은 ConcurrentLinkedHashMap

  • 에 따라 두 가지 구현

    • 동시 제공은 당신이 그것을 here을 찾을 수의 LinkedHashMap

    에 따라 동기화.

  • +0

    Maven Central에서 라이브러리를 출시 하시겠습니까? –

    +1

    버전 1.0은 지금 중앙에 있어야합니다 :) – Daimon

    1

    Here은 Java에서 매우 간단하고 사용하기 쉬운 LRU 캐시입니다. 짧고 간단하지만 생산 품질입니다. 코드가 설명되어 있으며 (README.md 참고) 일부 단위 테스트가 있습니다.

    11

    다음은 메모리에 최적의 수의 요소를 유지할 수 있도록 구현 한 것입니다.

    핵심은 MRU 개체에 대해 LinkedHashMap과 LRU 개체에 WeakHashMap의 조합을 사용하고 있기 때문에 현재 어떤 개체가 사용되고 있는지 추적 할 필요가 없다는 것입니다. 캐시 용량은 GC가 유지할 수있는 MRU 크기에 더한 값 이상입니다. 객체가 MRU에서 떨어져 나올 때마다 GC가 해당 객체를 가질 때까지 LRU로 이동합니다.

    public class Cache<K,V> { 
    final Map<K,V> MRUdata; 
    final Map<K,V> LRUdata; 
    
    public Cache(final int capacity) 
    { 
        LRUdata = new WeakHashMap<K, V>(); 
    
        MRUdata = new LinkedHashMap<K, V>(capacity+1, 1.0f, true) { 
         protected boolean removeEldestEntry(Map.Entry<K,V> entry) 
         { 
          if (this.size() > capacity) { 
           LRUdata.put(entry.getKey(), entry.getValue()); 
           return true; 
          } 
          return false; 
         }; 
        }; 
    } 
    
    public synchronized V tryGet(K key) 
    { 
        V value = MRUdata.get(key); 
        if (value!=null) 
         return value; 
        value = LRUdata.get(key); 
        if (value!=null) { 
         LRUdata.remove(key); 
         MRUdata.put(key, value); 
        } 
        return value; 
    } 
    
    public synchronized void set(K key, V value) 
    { 
        LRUdata.remove(key); 
        MRUdata.put(key, value); 
    } 
    } 
    
    +0

    멋진 접근 방법입니다. 따라서 LRU 캐시는 크기 제한 MRU 캐시에서 이미 만료 된 항목을 저장합니다. 이것은 소프트웨어의 2 차 캐시와 같습니다. 좋은! –

    +0

    나에게 grok에 분을 가져 갔다. 그러나 매우 시원한! – benkc

    +0

    LRU 데이터에 데이터가 있지만 MRU 데이터에 누락 된 데이터가있는 경우 캐시 크기 증가에 대한 응용 프로그램 로그에 경고 또는 힌트가 유용 할 수 있습니다. –

    관련 문제