1. 程式人生 > >Java進程內緩存

Java進程內緩存

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;

    public
ValueWithTimeStamp(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進程內緩存