만료 키가있는 Java 시간 기반 맵 / 캐시 [닫기] 충족하지 않습니다 . 현재

지정된 시간 초과 후 항목을 자동으로 제거하는 Java Map 또는 유사한 표준 데이터 저장소에 대해 알고 있습니까? 이는 오래된 만료 된 항목이 자동으로 “나중 만료”되는 에이징을 의미합니다.

Maven을 통해 액세스 할 수있는 오픈 소스 라이브러리에서?

기능을 직접 구현하고 과거에 여러 번 수행 한 방법을 알고 있으므로 그 점에서 조언을 구하는 것이 아니라 좋은 참조 구현을 가리키는 포인터입니다.

WeakHashMap 과 같은 WeakReference 기반 솔루션 은 옵션이 아닙니다. 내 키는 비 인턴 문자열 일 가능성이 높으며 가비지 수집기에 의존하지 않는 구성 가능한 시간 초과가 필요하기 때문입니다.

Ehcache 는 외부 구성 파일이 필요하기 때문에 의존하고 싶지 않은 옵션입니다. 코드 전용 솔루션을 찾고 있습니다.



답변

예. Google Collections 또는 Guava 는 이제 이름을 딴 MapMaker 라는 것을 가지고 있습니다.

ConcurrentMap<Key, Graph> graphs = new MapMaker()
   .concurrencyLevel(4)
   .softKeys()
   .weakValues()
   .maximumSize(10000)
   .expiration(10, TimeUnit.MINUTES)
   .makeComputingMap(
       new Function<Key, Graph>() {
         public Graph apply(Key key) {
           return createExpensiveGraph(key);
         }
       });

최신 정보:

구아바 10.0 (2011 년 9 월 28 일 출시) 기준으로, 이러한 많은 MapMaker 메소드는 새로운 CacheBuilder 를 위해 더 이상 사용되지 않습니다 .

LoadingCache<Key, Graph> graphs = CacheBuilder.newBuilder()
    .maximumSize(10000)
    .expireAfterWrite(10, TimeUnit.MINUTES)
    .build(
        new CacheLoader<Key, Graph>() {
          public Graph load(Key key) throws AnyException {
            return createExpensiveGraph(key);
          }
        });


답변

이것은 동일한 요구 사항과 동시성에 대해 수행 한 샘플 구현입니다. 누군가에게 유용 할 수 있습니다.

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 
 * @author Vivekananthan M
 *
 * @param <K>
 * @param <V>
 */
public class WeakConcurrentHashMap<K, V> extends ConcurrentHashMap<K, V> {

    private static final long serialVersionUID = 1L;

    private Map<K, Long> timeMap = new ConcurrentHashMap<K, Long>();
    private long expiryInMillis = 1000;
    private static final SimpleDateFormat sdf = new SimpleDateFormat("hh:mm:ss:SSS");

    public WeakConcurrentHashMap() {
        initialize();
    }

    public WeakConcurrentHashMap(long expiryInMillis) {
        this.expiryInMillis = expiryInMillis;
        initialize();
    }

    void initialize() {
        new CleanerThread().start();
    }

    @Override
    public V put(K key, V value) {
        Date date = new Date();
        timeMap.put(key, date.getTime());
        System.out.println("Inserting : " + sdf.format(date) + " : " + key + " : " + value);
        V returnVal = super.put(key, value);
        return returnVal;
    }

    @Override
    public void putAll(Map<? extends K, ? extends V> m) {
        for (K key : m.keySet()) {
            put(key, m.get(key));
        }
    }

    @Override
    public V putIfAbsent(K key, V value) {
        if (!containsKey(key))
            return put(key, value);
        else
            return get(key);
    }

    class CleanerThread extends Thread {
        @Override
        public void run() {
            System.out.println("Initiating Cleaner Thread..");
            while (true) {
                cleanMap();
                try {
                    Thread.sleep(expiryInMillis / 2);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }

        private void cleanMap() {
            long currentTime = new Date().getTime();
            for (K key : timeMap.keySet()) {
                if (currentTime > (timeMap.get(key) + expiryInMillis)) {
                    V value = remove(key);
                    timeMap.remove(key);
                    System.out.println("Removing : " + sdf.format(new Date()) + " : " + key + " : " + value);
                }
            }
        }
    }
}

Git Repo Link (리스너 구현)

https://github.com/vivekjustthink/WeakConcurrentHashMap

건배!!


답변

자체 만료 해시 맵의 구현 을 시도해 볼 수 있습니다 . 이 구현에서는 스레드를 사용하여 만료 된 항목을 제거하지 않고 모든 작업에서 자동으로 정리되는 DelayQueue 를 사용 합니다 .


답변

Apache Commons에는 Map에 항목을 만료하도록 데코레이터가 있습니다. PassiveExpiringMap
Guava의 캐시보다 간단합니다.

추신. 동기화되지 않았습니다.


답변

ehcache와 같은 소리는 원하는대로 과잉이지만 외부 구성 파일이 필요하지 않습니다.

일반적으로 구성을 선언적 구성 파일로 이동하는 것이 좋습니다 (따라서 새 설치에 다른 만료 시간이 필요할 때 다시 컴파일 할 필요는 없지만), 전혀 필요하지는 않지만 프로그래밍 방식으로 구성 할 수 있습니다. http://www.ehcache.org/documentation/user-guide/configuration


답변

Google 컬렉션 (구아바)에는 시간 제한 (만료)을 설정할 수 있는 MapMaker 가 있으며 팩토리 방법을 사용하여 선택한 인스턴스를 생성 할 때 약하거나 약한 참조를 사용할 수 있습니다.


답변

Apache MINA 프로젝트에서 Expiring Map http://www.java2s.com/Code/Java/Collections-Data-Structure/ExpiringMap.htm 클래스를 사용해 볼 수 있습니다.