Java進程內緩存
阿新 • • 發佈:2017-06-29
set style 定期刪除 pre 獲取 exception logs turn long
今天和同事聊到了緩存,在Java中實現進程緩存。這裏主要思想是,用一個map做緩存。緩存有個生存時間,過期就刪除緩存。這裏可以考慮兩種刪除策略,一種是起一個線程,定期刪除過期的key。第二個是,剔除模式,比較懶,訪問到某個key的時候才,才去檢查這個key是否過期,過期刪除。
首先,對要緩存的value做了層封裝,帶了個時間戳
/** * Created by gxf on 2017/6/28. */ public class ValueWithTimeStamp<V>{ private long expireTime; private V value; publicValueWithTimeStamp(long expireTime, V value) { this.expireTime = expireTime; this.value = value; } public long getExpireTime() { return expireTime; } public void setExpireTime(long expireTime) { this.expireTime = expireTime; } public V getValue() {return value; } public void setValue(V value) { this.value = value; } }
ok,起線程定期刪除策略的模式
import java.util.Map; import java.util.concurrent.ConcurrentHashMap; /** * Created by gxf on 2017/6/28. * 使用線程,定期刪除過期的key */ public class CacheMap<K, V> { //這裏使用ConcurrentHashMap避免,clean的時候,主線程修改chache,造成異常,//使用ConcurrentHashMap可以控制並發修改cache private Map<K, ValueWithTimeStamp<V>> cache = new ConcurrentHashMap<K, ValueWithTimeStamp<V>>(); private static boolean cleanTaskIsRunning = false; //ttl 過期時間 單位:秒 public void put(K key, V value, int ttl){ long expireTime = System.currentTimeMillis() + ttl * 1000; ValueWithTimeStamp<V> valueWithTimeStamp = new ValueWithTimeStamp<>(expireTime, value); cache.put(key, valueWithTimeStamp); if(!cleanTaskIsRunning){ startCleanTask(); cleanTaskIsRunning = !cleanTaskIsRunning; } } public V get(K key){ ValueWithTimeStamp<V> valueWithTimeStamp = cache.get(key); return null == valueWithTimeStamp ? null : valueWithTimeStamp.getValue(); } /** * 啟動清理線程 * */ private void startCleanTask(){ Thread cleanThread = new Thread(new CleanTask()); cleanThread.start(); } /** * 清理過期的key * */ class CleanTask implements Runnable{ public void run(){ while(true){ long currentTime = System.currentTimeMillis(); //遍歷map for(Map.Entry<K, ValueWithTimeStamp<V>> entry : cache.entrySet()){ ValueWithTimeStamp<V> valueWithTimeStamp = entry.getValue(); long expireTime = valueWithTimeStamp.getExpireTime(); //過期時間到了 if(currentTime > expireTime){ System.out.println("key : " + entry.getKey() + " expired "); cache.remove(entry.getKey()); } //if } //for //每隔1s掃描map對象 try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } } //while } } }
註意,這裏需要使用ConcurrentHashMap做緩存。不然會出現多線線程操作map對象的異常
第二種策略,剔除模式
import java.util.Map; import java.util.concurrent.ConcurrentHashMap; /** * Created by 58 on 2017/6/28. * 這裏使用懶惰模式,獲取key的時候,才剔除過期的key */ public class CacheMap1<K, V> { private Map<K, ValueWithTimeStamp<V>> cache = new ConcurrentHashMap<K, ValueWithTimeStamp<V>>(); public void put(K key, V value, int ttl){ long expireTime = System.currentTimeMillis() + ttl * 1000; ValueWithTimeStamp<V> valueWithTimeStamp = new ValueWithTimeStamp<V>(expireTime, value); cache.put(key, valueWithTimeStamp); } public V get(K key){ ValueWithTimeStamp<V> valueWithTimeStamp = cache.get(key); long expireTime = valueWithTimeStamp.getExpireTime(); long currentTime = System.currentTimeMillis(); //key已經過期,刪除,返回null if(currentTime > expireTime){ System.out.println("key :" + key + " is expired."); cache.remove(key); return null; } return cache.get(key).getValue(); } }
項目中用到了redis,用這種方式應該會更快,這兩天優化一下代碼
Java進程內緩存