LRU緩存

用Java的LinkedHashMap實現緩存,自定義LRULinkedHashMap繼承LinkedHashMap用作緩存數據保存,Cache類定義緩存方法接口,自定義類WaitingUpdateQueue封裝ConcurrentLinkedQueue和mina框架的ConcurrentHashSet類實現要向緩存中添加待加入元素,同時判斷重複元素,MemoryCache即爲緩存類。

1.Cache接口

package com.game.cache;

import java.util.List;

/** 
 * 內存緩存接口	@
 */
public interface Cache<K, V> {
	
	//獲得緩存結果
	public V get(K key);
	
	//放入緩存
	public void put(K key, V value);
	
	//移除緩存
	public void remove(K key);
	
	//取得最近要更新的記錄
	public List<V> getWaitingSave(int size);
}

2.LRULinkedHashMap數據保存集合類


package com.game.cache.structs;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * LRU緩存集合<br>
 * LinkedHashMap提供特殊的構造方法來創建鏈接哈希映射,該哈希映射的迭代順序就是最後訪問其條目的順序,從近期訪問最少到近期訪問最多的順序(訪問順序)。
 * 這種映射很適合構建 LRU 緩存。	@
 * */
public class LRULinkedHashMap<K, V> extends LinkedHashMap<K, V> {

	private static final long serialVersionUID = -3791412708654730531L;
	//最大數量
	private int max = 16;
	
	private static final int START_NUMBER = 16;
	
	private static final float DEFAULT_LOAD_FACTOR = 0.75f;
	
	private Lock lock = new ReentrantLock();
	
	public LRULinkedHashMap(int max){
		super(START_NUMBER, DEFAULT_LOAD_FACTOR, true);
		this.max = max;
	}

	/**集合大於指定大小時觸發,移除最老的元素*/
	public boolean removeEldestEntry(Map.Entry<K, V> eldest) {
		return size() > max;
	}
	
	public List<V> getEldestEntry(int size){
		try{
			lock.lock();
			List<V> result = new ArrayList<V>();
			Iterator<java.util.Map.Entry<K, V>> iterator = this.entrySet().iterator();
			while (iterator.hasNext()) {
				if(result.size() >= size){
					break;
				}
				Map.Entry<K, V> entry = (Map.Entry<K, V>) iterator.next();
				result.add(entry.getValue());
			}
			
			return result;
		}
		finally{
			lock.unlock();
		}
	}
	
	public V get(Object k){
		try{
			lock.lock();
			return super.get(k);
		}
		finally{
			lock.unlock();
		}
	}
	
	public V put(K key, V value){
		try{
			lock.lock();
			return super.put(key, value);
		}
		finally{
			lock.unlock();
		}
	}
	
	public V remove(Object key){
		try{
			lock.lock();
			return super.remove(key);
		}
		finally{
			lock.unlock();
		}
	}
}

3.WaitingUpdateQueue

package com.game.cache.structs;

import java.io.Serializable;
import java.util.concurrent.ConcurrentLinkedQueue;

import org.apache.mina.util.ConcurrentHashSet;

/** 
 * 
 * 更新等待隊列(實現隊列中含有值情況下不會重複添加),對ConcurrentLinkedQueue的封裝	@
 */
public class WaitingUpdateQueue<V> implements Serializable {

	private static final long serialVersionUID = -6020192336030291965L;
	//Value隊列
	private ConcurrentLinkedQueue<V> queue = new ConcurrentLinkedQueue<V>();
	//用於判斷是否重複添加元素
	private ConcurrentHashSet<V> set = new ConcurrentHashSet<V>();
	
	/**
	 * 添加到隊列中
	 * @param v
	 */
	public void add(V value){
		//未添加到過隊列
		if(!set.contains(value)){
			//Value添加到Set中
			set.add(value);
			//Value添加到隊列中
			queue.add(value);
		}
	}
	
	/**
	 * 獲得隊列頭部元素並移除
	 * @return
	 */
	public V poll(){
		//取得隊列頭部
		V value = queue.poll();
		//從隊列中移除Value
		if(value!=null) set.remove(value);
		return value;
	}
	
	/**
	 * 是否包含元素
	 * @param value
	 * @return
	 */
	public boolean contains(V value){
		return set.contains(value);
	}
	
	/**
	 * 移除元素
	 * @param value
	 */
	public void remove(V value){
		set.remove(value);
		queue.remove(value);
	}
}

4.MemoryCache

package com.game.cache.impl;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;

import com.game.cache.Cache;
import com.game.cache.structs.LRULinkedHashMap;
import com.game.cache.structs.WaitingUpdateQueue;

/** 
 * 
 * 內存緩存類實現	@
 */
public class MemoryCache<K, V> implements Cache<K, V>, Serializable {
	
	private static final long serialVersionUID = -3656956459941919920L;
	
	//緩存最大容量
	private static int MAX_SIZE = 5000;
	//每次保存數據量
	private static int PER_SAVE = 5;
	//每次保存數據量
	protected int saveSize;
	//內存緩存,存放元素的集合
	private LRULinkedHashMap<K, V> cache;
	//更新隊列
	private WaitingUpdateQueue<V> queue = new WaitingUpdateQueue<V>();

	
	public MemoryCache(){
		this(MAX_SIZE, PER_SAVE);
	}
	
	public MemoryCache(int maxSize, int saveSize){
		cache = new LRULinkedHashMap<K, V>(maxSize);
		this.saveSize = saveSize;
	}
	/**
	 * 添加到緩存中
	 */
	@Override
	public synchronized void put(K key, V value){
		//緩存中已存在
		if(cache.containsKey(key)){
			//添加到等待更新隊列
			queue.add(value);
			return;
		}
		cache.put(key, value);
	}
	
	/**
	 * 從緩存中獲得數據
	 */
	@Override
	public V get(K key) {
		//緩存中取數據
		V value = cache.get(key);
		return value;
	}
	
	/**
	 * 從緩存中移除數據
	 */
	@Override
	public void remove(K key){
		//緩存中取數據
		V value = cache.get(key);
		if(value!=null){
			//緩存移除數據
			cache.remove(key);
			//更新隊列移除數據
			queue.remove(value);
		}
	}
	
	/**
	 * 獲得更新數據
	 */
	@Override
	public List<V> getWaitingSave(int size) {
		ArrayList<V> waiting = new ArrayList<V>();
		//保存數量
		int i = 0;
		//隊列彈出數據
		V value = queue.poll();
		while (value != null) {
			waiting.add(value);
			i++;
			if(i == size) break;
			//隊列彈出數據
			value = queue.poll();
		}
		return waiting;
	}
	
	/**
	 * 獲得全部更新數據
	 */
	public List<V> getAllWaitingSave() {
		ArrayList<V> waiting = new ArrayList<V>();
		//隊列彈出數據
		V value = queue.poll();
		while (value != null) {
			waiting.add(value);
			//隊列彈出數據
			value = queue.poll();
		}
		return waiting;
	}
	
	public LRULinkedHashMap<K, V> getCache(){
		return cache;
	}
}




發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章