Posted By

kubaitis on 11/01/10


Tagged

map cache collections Concurrent caching


Versions (?)

Who likes this?

1 person have marked this snippet as a favorite

kubaitis


ConcurrentCacheMap


 / Published in: Java
 

Great for just about any kind of key/value in-memory caching... scales up to the limitations of the JVM, so it's about as good as it gets without clustering.

  1. import java.util.concurrent.ConcurrentMap;
  2. import java.util.concurrent.ConcurrentLinkedQueue;
  3. import java.util.concurrent.ConcurrentHashMap;
  4. import java.util.Set;
  5. import java.util.Collection;
  6. import java.util.Map;
  7. import java.io.Serializable;
  8. public class ConcurrentCacheMap<K,V> extends Thread implements ConcurrentMap<K,V>, Serializable {
  9. private ConcurrentLinkedQueue<K> queue;
  10. private ConcurrentHashMap<K,V> cache;
  11. private ConcurrentHashMap<K,Long> cacheDates;
  12. private Long lastSpringCleaning;
  13. private Long timeToLive;
  14. private Long springCleaningInterval;
  15. private Integer size;
  16. public ConcurrentCacheMap(){
  17. queue = new ConcurrentLinkedQueue<K>();
  18. cache = new ConcurrentHashMap<K,V>();
  19. size = 5000;
  20. lastSpringCleaning = System.currentTimeMillis();
  21. cacheDates = new ConcurrentHashMap<K,Long>();
  22. timeToLive = 1000L * 60L * 15L;
  23. springCleaningInterval = 1000L * 60L;
  24. }
  25. public ConcurrentCacheMap(int size){
  26. queue = new ConcurrentLinkedQueue<K>();
  27. cache = new ConcurrentHashMap<K,V>();
  28. this.size = size;
  29. lastSpringCleaning = System.currentTimeMillis();
  30. cacheDates = new ConcurrentHashMap<K,Long>();
  31. timeToLive = 1000L * 60L * 15L;
  32. springCleaningInterval = 1000L * 60L;
  33. }
  34. public ConcurrentCacheMap(int size,long timeToLive){
  35. queue = new ConcurrentLinkedQueue<K>();
  36. cache = new ConcurrentHashMap<K,V>();
  37. this.size = size;
  38. lastSpringCleaning = System.currentTimeMillis();
  39. cacheDates = new ConcurrentHashMap<K,Long>();
  40. this.timeToLive = timeToLive;
  41. springCleaningInterval = 1000L * 60L;
  42. }
  43. public ConcurrentCacheMap(int size,long timeToLive,long springCleaningInterval){
  44. queue = new ConcurrentLinkedQueue<K>();
  45. cache = new ConcurrentHashMap<K,V>();
  46. this.size = size;
  47. lastSpringCleaning = System.currentTimeMillis();
  48. cacheDates = new ConcurrentHashMap<K,Long>();
  49. this.timeToLive = timeToLive;
  50. this.springCleaningInterval = springCleaningInterval;
  51. }
  52. public V get(Object key){ V result = cache.get(key); housekeeping(); return result; }
  53. public boolean isCached(K key){ housekeeping(); return cache.containsKey(key);}
  54. public void clear(){ queue.clear(); cache.clear(); cacheDates.clear();}
  55. public Set<K> keySet(){ housekeeping(); return cache.keySet(); }
  56. public Collection<V> values(){ housekeeping(); return cache.values();}
  57. public Set<Map.Entry<K,V>> entrySet(){ housekeeping(); return cache.entrySet(); }
  58. public V replace(K key, V value){ housekeeping(); return cache.replace(key,value); }
  59. public boolean replace(K key, V oldValue,V newValue){ housekeeping(); return cache.replace(key,oldValue,newValue); }
  60. public void setMaxSize(Integer size){ this.size = size; }
  61. public void setTimeToLive(Long timeToLive){ this.timeToLive = timeToLive; }
  62. public void setSpringCleaningInterval(Long springCleaningInterval){ this.springCleaningInterval = springCleaningInterval; }
  63. public Integer getMaxSize(){ return size; }
  64. public Long getTimeToLive(){ return timeToLive; }
  65. public boolean containsKey(Object key){return cache.containsKey(key);}
  66. public boolean containsValue(Object value){return cache.containsValue(value);}
  67. public boolean isEmpty(){return cache.isEmpty();}
  68. public int size(){ return cache.size(); }
  69. public Long getSpringCleaningInterval(){ return springCleaningInterval; }
  70. public V remove(Object key){
  71. V result = cache.remove(key);
  72. queue.remove(key);
  73. cacheDates.remove(key);
  74. housekeeping();
  75. return result;
  76. }
  77. public boolean remove(Object key,Object value){
  78. boolean result = false;
  79. if(cache.get(key).equals(value)){
  80. result = cache.remove(key,value);
  81. queue.remove(key);
  82. cacheDates.remove(key);
  83. }
  84. housekeeping();
  85. return result;
  86. }
  87. public V putIfAbsent(K key,V value){
  88. V result = null;
  89. if(!cache.containsKey(key)){
  90. cache.put(key,value);
  91. queue.add(key);
  92. cacheDates.put(key,System.currentTimeMillis());
  93. } else { result = cache.get(key);}
  94. housekeeping();
  95. return result;
  96. }
  97. public V put(K key,V object){
  98. V result = null;
  99. if(!cache.containsKey(key)){
  100. cache.put((K)key,(V)object);
  101. queue.add((K)key);
  102. cacheDates.put((K)key,System.currentTimeMillis());
  103. } else {
  104. result = cache.get(key);
  105. cache.replace((K)key,(V)object);
  106. cacheDates.replace((K)key,System.currentTimeMillis());
  107. }
  108. housekeeping();
  109. return result;
  110. }
  111. public void putAll(Map<? extends K,? extends V> map){
  112. housekeeping();
  113. for(Object o : map.entrySet()){
  114. Map.Entry me = (Map.Entry) o;
  115. put((K)me.getKey(),(V)me.getValue());
  116. }
  117. }
  118. public void housekeeping(){
  119. Thread t = new Thread();
  120. t.start();
  121. }
  122. public void run(){
  123. while(queue.size() > size){
  124. Object key = queue.poll();
  125. if(key != null){
  126. cache.remove(key);
  127. queue.remove(key);
  128. cacheDates.remove(key);
  129. }
  130. }
  131. Long now = System.currentTimeMillis();
  132. if(lastSpringCleaning + springCleaningInterval < now){
  133. springCleaning(now);
  134. }
  135. }
  136. public void springCleaning(Long now){
  137. Object key;
  138. for(Map.Entry<? extends K,Long> me : cacheDates.entrySet()){
  139. if(me.getValue() + timeToLive < now){
  140. key = me.getKey();
  141. cache.remove(key);
  142. queue.remove(key);
  143. cacheDates.remove(key);
  144. }
  145. }
  146. }
  147. }

Report this snippet  

You need to login to post a comment.