Легкий, простой в использовании кэш LRU в java
Я знаю, что это просто реализовать, но я хочу использовать то, что уже существует.
проблема, которую я хочу решить, заключается в том, что я загружаю конфигурацию (из XML, поэтому я хочу кэшировать их) для разных страниц, ролей,... так что комбинация входов может вырасти довольно сильно (но в 99% не будет). Чтобы справиться с этим 1%, я хочу иметь некоторое максимальное количество элементов в кэше...
пока не знаю, что я нашел org.апаш.палата общин.коллекции.карта.LRUMap в Apache commons И это выглядит нормально, но хочу проверить еще кое-что. Какие-нибудь рекомендации?
5 ответов:
вы можете использовать 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);
Это старый вопрос, но для потомков я хотел перечислить ConcurrentLinkedHashMap, который является потокобезопасным, в отличие от LRUMap. Использование довольно легко:
ConcurrentMap<K, V> cache = new ConcurrentLinkedHashMap.Builder<K, V>() .maximumWeightedCapacity(1000) .build();
и документация имеет некоторые хорошие примеры, например, как сделать размер кэша LRU на основе вместо количества элементов на основе.
вот моя реализация, которая позволяет мне сохранить оптимальное количество элементов в памяти.
дело в том, что мне не нужно отслеживать, какие объекты в настоящее время используются, так как я использую комбинацию LinkedHashMap для объектов MRU и WeakHashMap для объектов LRU. Таким образом, емкость кэша не меньше размера MRU плюс все, что GC позволяет мне сохранить. Всякий раз, когда объекты падают с MRU, они идут в LRU до тех пор, пока GC будет иметь их.
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 обеспечивает потокобезопасное, очень простое, не распределенное кэширование LRU с поддержкой TTL. Он предоставляет две реализации
- Concurrent на основе ConcurrentLinkedHashMap
- синхронизировано на основе LinkedHashMap
вы можете найти здесь.
здесь это очень простой и легкий в использовании кэш LRU в Java. Хотя она коротка и проста это качество продукции. Код объяснен (посмотрите на README.md) и имеет некоторые модульные тесты.