Java代码实现Cache
本文参考网络上其它文章,仅做部分代码修改及优化,加入个人编码习惯,感谢那些乐于分享的大佬吧
package com.yt.test.callback2; import java.util.concurrent.Delayed; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; /** * 延迟队列元素,未达到指定时间,则不可使用此对象,单独使用也是不错的工具类 * * @author ChenSS on 2017年9月13日 * @param <T> */ public class DelayItem<T> implements Delayed { private long timeout; private long endTime; private T item; public DelayItem(T item, long timeout) { this.item = item; this.timeout = timeout; this.endTime = System.nanoTime() + TimeUnit.NANOSECONDS.convert(timeout, TimeUnit.MILLISECONDS); } public DelayItem(T item, long timeout, TimeUnit unit) { this.item = item; this.timeout = timeout; this.endTime = System.nanoTime() + TimeUnit.NANOSECONDS.convert(timeout, unit); } public T getItem() { return this.item; } public long getTimeout() { return timeout; } /** * 重置结束时间 * * @throws TimeoutException * 如果已经结束,不可被重置 */ public void reset() throws TimeoutException { if (System.nanoTime() > endTime) throw new TimeoutException("The current object has timeout, can not be reset"); this.endTime = System.nanoTime() + TimeUnit.NANOSECONDS.convert(timeout, TimeUnit.MILLISECONDS); } /** * 预计结束时间-当前时间 = 剩余停滞时间(当数值小于零时此对象可用) * * @return 纳秒(未达到超时时间对象不可用) */ @Override public long getDelay(TimeUnit unit) { return unit.convert((endTime - System.nanoTime()), TimeUnit.NANOSECONDS); } /** * 取出结束时间最早的 */ @Override public int compareTo(Delayed other) { if (other == this) return 0; if (other instanceof DelayItem) { long diff = endTime - ((DelayItem<?>) other).endTime; return (diff == 0) ? 0 : ((diff < 0) ? -1 : 1); } long diff = (getDelay(TimeUnit.NANOSECONDS) - other.getDelay(TimeUnit.NANOSECONDS)); return (diff == 0) ? 0 : ((diff < 0) ? -1 : 1); } @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + ((item == null) ? 0 : item.hashCode()); return result; } /** * 重写此方法方便在多数集合中以Item值比较DelayItem是否是同一个 */ @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; DelayItem<?> other = (DelayItem<?>) obj; if (item == null) { if (other.item != null) return false; } else if (!item.equals(other.item)) return false; return true; } }
package com.yt.test.callback2; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; import java.util.concurrent.DelayQueue; import java.util.concurrent.TimeUnit; import java.util.logging.Level; import java.util.logging.Logger; import javax.naming.TimeLimitExceededException; /** * * @author ChenSS on 2017年9月13日 * @param <K> * @param <V> */ public class Cache<K, V> { private Logger logger = Logger.getLogger(Cache.class.getName()); private DelayQueue<DelayItem<K>> q = new DelayQueue<>(); /** * 多线程安全的Maps */ private ConcurrentMap<K, V> maps = new ConcurrentHashMap<K, V>(); private long liveTime; /** * 守护进程 */ private Thread daemonThread; public Cache(long liveTime) { this.liveTime = liveTime; Runnable daemonTask = new Runnable() { public void run() { daemonCheck(); } }; daemonThread = new Thread(daemonTask); daemonThread.setDaemon(true); daemonThread.setName("Cache Daemon"); daemonThread.start(); } public void put(K key, V value) { this.put(key, value, liveTime, TimeUnit.MILLISECONDS); } public void put(K key, V value, long outtime) { this.put(key, value, outtime, TimeUnit.MILLISECONDS); } public void put(K key, V value, long outtime, TimeUnit timeUnit) { if (outtime <= 0) { try { throw new TimeLimitExceededException("Cache livetime below 0"); } catch (TimeLimitExceededException e) { e.printStackTrace(); } } V oldValue = maps.put(key, value); if (oldValue != null) q.remove(key); q.put(new DelayItem<K>(key, outtime, timeUnit)); } public V get(K key) { return maps.get(key); } private void daemonCheck() { if (logger.isLoggable(Level.INFO)) logger.info("cache service started."); for (;;) { try { DelayItem<K> delayItem = q.take(); if (delayItem != null) maps.remove(delayItem.getItem()); } catch (InterruptedException e) { if (logger.isLoggable(Level.SEVERE)) logger.log(Level.SEVERE, e.getMessage(), e); e.printStackTrace(); break; } } if (logger.isLoggable(Level.INFO)) logger.info("cache service stopped."); } }
package com.yt.test.callback2; public class Test { public static void main(String[] args) throws InterruptedException { Cache<String, Integer> cache = new Cache<>(4000); cache.put("AAAA", 3); cache.put("BBBB", 4, 4000); System.out.println(cache.get("AAAA")); Thread.sleep(3000); System.out.println(cache.get("BBBB")); Thread.sleep(1200); System.out.println(cache.get("AAAA")); System.out.println(cache.get("BBBB")); } }
疯狂的妞妞 :每一天,做什么都好,不要什么都不做!