自己实现的缓存
最近比较无聊,就自己写了一个Cache,已经实现了大概的功能
一.Cache缓存接口类
public interface Cache extends java.lang.Comparable {
// 放入元素
void put(CacheElement element) throws CacheException;
// 获取元素
CacheElement get(String key) throws CacheException;
// 重新刷新缓存
void refresh();
void list();
// 获取缓存的key
Set<String> getKeys();
void remove(String key);
// 清除缓存
void clear();
int getSize();
String getName();
void setName(String name);
String toString();
}
二。Storage 存取器接口,主要的实现类有 MemoryStorage,DiskStorage,MixStorage
public interface Storage<K, V> {// 能够容纳的最大存储对象。public int getMaxElementCnt();public CachePolicy getCachePolicy();// 存活时间,当存取器的对象超出等待时间,会自动从存取器中remove,// 当是0时,表示对象可以永远等待,不会过期public long getIdelSecond();// 存活时间,当存取器的对象超出存活时间,会自动从存取器中remove// 当是 0时,表示永远存活,不会过期public long getLiveSecond();// refresh缓存,将更存取器的对象访问时间和清除过期的对象public void refresh();public void put(CacheElement<K, V> element) throws CacheException;public CacheElement<K, V> get(String key);public CacheElement<K, V> remove(K key);public abstract void removeAll();// 根据 CachePolicy自动pickout出CacheElementpublic CacheElement<K, V> pickout();public abstract void dispose();public abstract int getSize();public boolean contain(String key);// 获取缓存key的Setpublic Set<K> getKeys();// 获取缓存entry的Setpublic Set<V> getEntry();}public class MemoryStorage<K, V> implements Storage, CacheSerializable<K, V> {private static final long serialVersionUID = 1L;private int maxElementCnt;private Map<K, CacheElement> map;private long idelSecond;private long liveSecond;private CachePolicy policy;private static Object lock = new Object();public MemoryStorage(int maxElementCnt, long liveSecond, long idelSecond,CachePolicy policy) {this.maxElementCnt = maxElementCnt;this.liveSecond = liveSecond;this.idelSecond = idelSecond;this.policy = policy;this.init(policy);}public MemoryStorage(int maxElementCnt) {this(maxElementCnt, 2, 2, CachePolicy.LFU);} public MemoryStorage() {this(1000, 0, 0, CachePolicy.LRU);}public CachePolicy getCachePolicy() {return policy;}public int getMaxElementCnt() {return maxElementCnt;}public long getIdelSecond() {return idelSecond;}public void setIdelSecond(long idelSecond) {this.idelSecond = idelSecond;}public long getLiveSecond() {return liveSecond;}public void setLiveSecond(long liveSecond) {this.liveSecond = liveSecond;}public void setMaxElementCnt(int maxElementCnt) {this.maxElementCnt = maxElementCnt;}private boolean isFull() {return this.getMaxElementCnt() == this.getSize();}public void refresh() { Set<K> keySet = this.map.keySet();if (keySet == null || keySet.isEmpty())return;Iterator<K> it = keySet.iterator();CacheElement element = null;Collection<K> collections = new ArrayList<K>();synchronized (lock) {while (it.hasNext()) {K next = it.next();element = (CacheElement) this.map.get(next);if (element.isExpired()) {collections.add(next);}}if (collections.size() > 0) {for (K k : collections) {this.map.remove(k);}}long curTime = System.currentTimeMillis();keySet = this.map.keySet();if (keySet == null || keySet.isEmpty())return;it = keySet.iterator();while (it.hasNext()) {element = this.map.get(it.next());element.setUpdateTime(curTime);}}}public void dispose() {// TODO Auto-generated method stub}public CacheElement<K, V> get(String key) {CacheElement<K, V> element = null;synchronized (lock) {if (this.map.containsKey(key)) {element = this.map.get(key);element.setUpdateTime(System.currentTimeMillis());element.setHitCnt(element.getHitCnt() + 1L);}if (this.policy == CachePolicy.LFU) {// 对元素按照 hitCnt重新排序} else if (this.policy == CachePolicy.LRU) {}}return element;}public int getSize() {return this.map.size();}public void put(CacheElement element) throws CacheException {synchronized (lock) {if (this.isFull()) {this.pickout();}if (element != null) {element.setStorage(this);this.map.put((K) element.getKey(), element);}}}public CacheElement<K, V> remove(Object key) {synchronized (lock) {if (map.containsKey(key)) {return map.remove(key);}}return null;}public void removeAll() {if (this.map.size() == 0) {return;}synchronized (lock) {this.map.clear();}}public boolean contain(String key) {return this.map.containsKey(key);}public Set<K> getKeys() {return this.map.keySet();}private void init(CachePolicy policy) {switch (policy) {case LFU:this.map = new HashMap<K, CacheElement>();break;case FIFO:this.map = new LinkedHashMap<K, CacheElement>();break;case LRU:this.map = new LinkedHashMap<K, CacheElement>();break;}}// 剔除一个元素 public CacheElement pickout() {if (this.getSize() <= 0) {return null;}CacheElement cache = null;Set<K> set = null;CacheElement[] caches = null;Iterator<K> it = null;int i = 0;switch (policy) {case LFU:set = this.map.keySet();caches = new CacheElement[set.size()];it = set.iterator();while (it.hasNext()) {caches[i++] = this.map.get(it.next());}Arrays.sort(caches, new Comparator<CacheElement>() {// 按 updateTime升序排列public int compare(CacheElement o1, CacheElement o2) {return (int) (o1.getHitCnt() - o2.getHitCnt());}});cache = caches[0];this.map.remove(caches[0].getKey());break;case FIFO:it = this.map.keySet().iterator();if (it.hasNext()) {cache = this.map.remove(it.next());}break;case LRU:set = this.map.keySet();caches = new CacheElement[set.size()];it = set.iterator();while (it.hasNext()) {caches[i++] = this.map.get(it.next());}Arrays.sort(caches, new Comparator<CacheElement>() {// 按 updateTime升序排列public int compare(CacheElement o1, CacheElement o2) {return (int) (o1.getUpdateTime() - o2.getUpdateTime());}});cache = caches[0];this.map.remove(cache.getKey());break;}return cache;}public Set<V> getEntry() {Set set = this.map.entrySet();Iterator<Map.Entry> it = set.iterator();Set<V> entrySet = new TreeSet<V>();while (it.hasNext()) {entrySet.add((V) it.next().getValue());}return entrySet;}}public final class CacheManagerFactoryBean {private CacheProvider provider;private String factoryName;public String getFactoryName() {return factoryName;}public void setFactoryName(String factoryName) {this.factoryName = factoryName;}public CacheProvider getProvider() {return provider;}public void setProvider(CacheProvider provider) {this.provider = provider;} public final Cache create(){ return this.create(null);} public final Cache create(Properties p){ return this.getProvider().buildCache(p);} } public class DefaultCacheProvider implements CacheProvider {private String providerName;private Set<Cache> cacheSet; private Properties defaultCacheProperties; private CacheSet cachSet; private static boolean register = false; public CacheSet getCachSet() {return cachSet;}public void setCachSet(CacheSet cachSet) {this.cachSet = cachSet;}public DefaultCacheProvider(){ if( register != true) { CacheProviderManager.getInstance().register( this.getClass().getName()+"-"+this.getProviderName(),this); register = true; } }public Properties getDefaultCacheProperties() {return defaultCacheProperties;}public void setDefaultCacheProperties(Properties defaultCacheProperties) {this.defaultCacheProperties = defaultCacheProperties;}public String getProviderName() {return providerName;}public void setProviderName(String providerName) {this.providerName = providerName;} public Cache buildCache(Properties selfPro) { if( this.defaultCacheProperties == null ) { throw new CacheException("请先配置defaultCacheProperties属性"); } CacheSet cacheSet = new CacheSet(defaultCacheProperties,selfPro); Cache cache = new DefaultCacheImpl(cacheSet); this.getCaches().add(cache); return cache; } public Set<Cache> getCaches() {synchronized(this) { if( cacheSet == null) { cacheSet = new TreeSet<Cache>(); }} return cacheSet;}}六。cache.xml的spring配置文件<bean id="defaultCacheProvider" > <property name="providerName" value ="defaultProvider"> </property> <property name="defaultCacheProperties"> <props> <!-- cache的名字 --> <prop key="cache.name">defaultcache</prop> <!-- --> <prop key="cache.cache_policy">LFU</prop> <!-- memory,disk,mix 默认值是 memory --> <prop key="cache.cache_storage">memory</prop> <!-- 最大存储的最大元素的值 --> <prop key="cache.max_element_count">1000</prop> <!-- 等待时间 ,单位秒,0秒表示可以无限等待 --> <prop key="cache.idel_seconds">1000</prop> <!-- 存活时间 ,单位秒,0秒表示可以永远存活--> <prop key="cache.live_seconds">1000</prop> </props></property> </bean> <bean id="cacheFactory" value="defaultCacheFactory" /> <property name="provider"> <ref bean="defaultCacheProvider" /> </property> </bean> <bean id="cache1" factory-bean="cacheFactory" factory-method="create" > <constructor-arg> <props> <prop key="cache.name">mycache</prop> <prop key="cache.cache_policy">LFU</prop> <prop key="cache.cache_storage">memory</prop> <prop key="cache.max_element_count">1000</prop> <prop key="cache.idel_seconds">1</prop> <prop key="cache.live_seconds">2</prop> </props> </constructor-arg> </bean> <bean id="cache2" factory-bean="cacheFactory" factory-method="create" > </bean>
七。测试用例
public class CacheTest { public static void main(String[] args) throws Exception { ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(new String[]{"com/cache/cache.xml"}); Cache cache1 = (Cache) context.getBean("cache1"); System.out.println("cache1.name = " + cache1.getName()); /**/ CacheElement<String,Integer> element = null;for(int i = 1 ; i <=4; i++){element = new CacheElement<String,Integer>("key"+i,i);cache1.put(element);} cache1.list(); Cache cache2 = (Cache) context.getBean("cache2"); CacheElement<String,Integer> element2 = null;for(int i =5 ; i <=10; i++){element2 = new CacheElement<String,Integer>("key"+i,i);cache2.put(element2);} cache2.list();System.out.println("key1="+cache1.get("key1").getObjectValue()); System.out.println("key8="+cache2.get("key8").getObjectValue()); } }