Mercurial > hg > LGDataverses
comparison src/main/java/edu/harvard/iq/dataverse/util/LruCache.java @ 10:a50cf11e5178
Rewrite LGDataverse completely upgrading to dataverse4.0
| author | Zoe Hong <zhong@mpiwg-berlin.mpg.de> |
|---|---|
| date | Tue, 08 Sep 2015 17:00:21 +0200 |
| parents | |
| children |
comparison
equal
deleted
inserted
replaced
| 9:5926d6419569 | 10:a50cf11e5178 |
|---|---|
| 1 package edu.harvard.iq.dataverse.util; | |
| 2 | |
| 3 import java.util.LinkedHashMap; | |
| 4 import java.util.concurrent.locks.ReentrantLock; | |
| 5 | |
| 6 /** | |
| 7 * A thread-safe implementation of a capped-size cache, where the removal is done | |
| 8 * based on the "Least Recently Used" strategy. | |
| 9 * This implementation allows some scenarios where the removed values are not the | |
| 10 * least recently used, in order to provide better performance. | |
| 11 * | |
| 12 * @author michael | |
| 13 * @param <K> Class for the cache keys | |
| 14 * @param <V> Class for the cache values | |
| 15 */ | |
| 16 public class LruCache<K,V> { | |
| 17 private final LinkedHashMap<K, V> cache = new LinkedHashMap<>(10, 0.75f, true); | |
| 18 private final ReentrantLock cacheLock = new ReentrantLock(); | |
| 19 private long maxSize = 128; | |
| 20 | |
| 21 /** | |
| 22 * @param k The key to get | |
| 23 * @return The value associated with {@code k}, or {@code null}, if there isn't any. | |
| 24 */ | |
| 25 public V get( K k ) { | |
| 26 try { | |
| 27 cacheLock.lock(); | |
| 28 return cache.get(k); | |
| 29 } finally { cacheLock.unlock(); } | |
| 30 } | |
| 31 | |
| 32 /** | |
| 33 * Associates {@code k} with {@code v}. | |
| 34 * @param k the key | |
| 35 * @param v the value | |
| 36 * @return {@code v}, to allow method call chaining. | |
| 37 */ | |
| 38 public V put( K k, V v ) { | |
| 39 try { | |
| 40 cacheLock.lock(); | |
| 41 cache.put(k, v); | |
| 42 shrinkToMaxSize(); | |
| 43 return v; | |
| 44 } finally { cacheLock.unlock(); } | |
| 45 } | |
| 46 | |
| 47 public long size() { | |
| 48 try { | |
| 49 cacheLock.lock(); | |
| 50 return cache.size(); | |
| 51 } finally { cacheLock.unlock(); } | |
| 52 } | |
| 53 | |
| 54 public long getMaxSize() { | |
| 55 return maxSize; | |
| 56 } | |
| 57 | |
| 58 public void setMaxSize(long maxSize) { | |
| 59 if ( maxSize < 1 ) { | |
| 60 throw new IllegalArgumentException("Max cache size can't be less than 1"); | |
| 61 } | |
| 62 try { | |
| 63 cacheLock.lock(); | |
| 64 this.maxSize = maxSize; | |
| 65 shrinkToMaxSize(); | |
| 66 } finally { cacheLock.unlock(); } | |
| 67 } | |
| 68 | |
| 69 public void invalidate() { | |
| 70 try { | |
| 71 cacheLock.lock(); | |
| 72 cache.clear(); | |
| 73 } finally { cacheLock.unlock(); } | |
| 74 } | |
| 75 | |
| 76 public void invalidate( K k ) { | |
| 77 try { | |
| 78 cacheLock.lock(); | |
| 79 cache.remove(k); | |
| 80 } finally { cacheLock.unlock(); } | |
| 81 } | |
| 82 | |
| 83 private void shrinkToMaxSize() { | |
| 84 while( cache.size() > getMaxSize() ) { | |
| 85 cache.remove( cache.entrySet().iterator().next().getKey() ); | |
| 86 } | |
| 87 } | |
| 88 } |
