Nice programing

쉽고 간단하게 Java에서 LRU 캐시 사용

nicepro 2020. 11. 23. 20:00
반응형

쉽고 간단하게 Java에서 LRU 캐시 사용


구현이 간단하다는 것을 알고 있지만 이미 존재하는 것을 재사용하고 싶습니다.

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

아파치 커먼즈에서 org.apache.commons.collections.map.LRUMap을 찾았다는 것을 알기 전까지는 괜찮아 보이지만 다른 것도 확인하고 싶습니다. 권장 사항이 있습니까?


LinkedHashMap (Java 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);

이것은 오래된 질문이지만 후손을 위해 LRUMap 과 달리 스레드로부터 안전한 ConcurrentLinkedHashMap 을 나열하고 싶었 습니다 . 사용법은 매우 쉽습니다.

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

문서에는 항목 수 기반 대신 LRU 캐시 크기 기반을 만드는 방법과 같은 몇 가지 좋은 예가 있습니다.


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

요점은 MRU 개체에 LinkedHashMap과 LRU 개체에 WeakHashMap의 조합을 사용하고 있기 때문에 현재 사용중인 개체를 추적 할 필요가 없다는 것입니다. 따라서 캐시 용량은 MRU 크기와 GC가 유지할 수있는 것보다 작지 않습니다. 물체가 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);
}
}

나도 같은 문제가 있었고 좋은 라이브러리를 찾지 못했기 때문에 내 자신의 라이브러리를 만들었습니다.

simplelrucache는 TTL 지원을 통해 스레드로부터 안전하고 매우 간단한 비 분산 LRU 캐싱을 제공합니다. 두 가지 구현을 제공합니다.

  • Concurrent based on ConcurrentLinkedHashMap
  • Synchronized based on LinkedHashMap

You can find it here.


Here is a very simple and easy to use LRU cache in Java. Although it is short and simple it is production quality. The code is explained (look at the README.md) and has some unit tests.

참고URL : https://stackoverflow.com/questions/224868/easy-simple-to-use-lru-cache-in-java

반응형