MyLRUCache 缓存类
package org.jf.alg.lru;
import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
/**
* 限定容量二叉堆+HashMap实现LRU
*
* @author junfeng.chen
*
*/
public class MyLRUCache {
private Map<Object,ValueEntry> container = Collections.synchronizedMap( new HashMap<Object,ValueEntry>());
private List<Object> visistList = Collections.synchronizedList(new LinkedList<Object>());//key值的访问历史
private KeyVisitCounter[] heap_array ;
private int increaseStep = 500 ;
private int initSize = 2000;
//访问记录列表 每次访问元素,将其访问记录放入列表,并有后台线程处理
private long reset_interval = 2000*60;//刷新时间默认为2分钟
private int capacity = 100000;
private int size = 0;
private boolean bln_started = false;
private PerlocateThread perlocateThd ;
public MyLRUCache()
{
init();
}
public MyLRUCache(int capacity)
{
this.capacity = capacity;
init();
}
/**
*
* @param capacity 最大容量
* @param time_cycle 计数时间周期
*/
public MyLRUCache(int capacity,int time_cycle)
{
this.capacity = capacity;
this.reset_interval = time_cycle;
init();
}
public void start()
{
this.perlocateThd = new PerlocateThread();
perlocateThd.start();
this.bln_started = true;
}
public void stop()
{
if(perlocateThd != null)
perlocateThd.exit();
this.bln_started = false;
this.heap_array = new KeyVisitCounter[this.initSize+1];
this.visistList.clear();
this.container.clear();
}
private void init()
{
this.heap_array = new KeyVisitCounter[this.initSize+1];
}
public void resetCount()
{
for(KeyVisitCounter counter:heap_array)
{
if(counter != null)
counter.reSet();
else
break;
}
}
// public void remove(Object key)
// {
// not support remove explicity
// }
//
public Object get(Object key)
{
assertStatus();
ValueEntry valueEntry = this.container.get(key);
if(valueEntry != null)
{
//在堆中查找当前key,并对其count加1
visistList.add(key);
return valueEntry.getData();
}
return null;
}
public void put(Object key,Object value)
{
assertStatus();
ValueEntry entry = new ValueEntry(value);
this.visistList.add(key);
this.container.put(key, entry);//实际上 保存的元素可能比capacity多
}
public int getSize()
{
return this.size;
}
/***********************some help methods****************************************************/
private void assertStatus()
{
if(!this.bln_started)
throw new RuntimeException("Illegle Cache Staus,not started");
}
/**
*
* @param key
* @return 该key值对应的索引
*/
private int perlocateUp(Object key/* , ValueEntry entry*/)
{
int indx = -1;
ValueEntry entry = container.get(key);
if(entry.getKeyIndx()==-1)
{
if(size<this.capacity&&size==this.heap_array.length-1)
{
int step = this.capacity - this.size;
step = step<=this.increaseStep?step:increaseStep;
KeyVisitCounter []newArray = new KeyVisitCounter[heap_array.length+step];
System.arraycopy(heap_array, 1, newArray,1, size);
heap_array = newArray;
}
KeyVisitCounter key_counter = new KeyVisitCounter(key);
key_counter.visit();//缓存已满时,防止最后一个元素总是被删除 刚插入的元素给予特殊待遇
//新加入一个记录值
if(this.size==this.capacity)//heap满
{
if(heap_array[size].compareTo(key_counter)<=0)
{
heap_array[size] = key_counter;
indx = size;
}//else indx = -1
}else
{
heap_array[size+1] = key_counter;
indx = size+1;
size++;
}
entry.setKeyIndex(indx);
}
else
{
indx = entry.getKeyIndx();
}
if(indx == -1)//
return -1;
//fix up heap_array to ensure it's heap character
int parent = indx/2;
KeyVisitCounter counter = this.heap_array[indx];
counter.visit();
while(parent!=0)
{
if(this.heap_array[indx].compareTo(this.heap_array[parent])>0)
{
KeyVisitCounter tmp = heap_array[indx];
heap_array[indx] = heap_array[parent];
heap_array[parent] = tmp;
indx = parent;
//设置key对应的索引
this.container.get(heap_array[indx].getKey()).setKeyIndex(indx);
this.container.get(heap_array[parent].getKey()).setKeyIndex(parent);
parent = indx/2;
}else
{
break;
}
}
return indx;
}
private class PerlocateThread extends Thread
{
boolean run = true;
public void run()
{
int count = 200;
long last_reset_time = System.currentTimeMillis();
while(run)
{
while(count>0&&visistList.size()>0)
{
Object key = visistList.remove(0);
int indx = perlocateUp(key);
if(indx == -1)
container.remove(key);
}
if(System.currentTimeMillis() - last_reset_time >reset_interval)
{
resetCount();
last_reset_time = System.currentTimeMillis();
}
try {
this.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
break;
}
}
}
public void exit()
{
run = false;
}
}
}
访问次数记录类
package org.jf.alg.lru;
public class KeyVisitCounter implements Comparable{
private Object key;
private int count;
public KeyVisitCounter(Object key)
{
this.key = key;
}
public void visit()
{
count++;
}
public void visit(int times)
{
this.count += times ;
}
public int getVisitTimes()
{
return count;
}
public Object getKey()
{
return this.key;
}
public void reSet()
{
this.count = 0;
}
@Override
public int compareTo(Object o)
{
if(!(o instanceof KeyVisitCounter))
return 1;
KeyVisitCounter counter = (KeyVisitCounter) o;
if(this.count > counter.count)
return 1;
if(this.count == counter.count)
return 0;
return -1;
}
}
package org.jf.alg.lru;
public class ValueEntry {
private int keyIndx = -1;//key在heap数组中的下标
private Object data;
public ValueEntry(Object data)
{
this.data = data;
}
public Object getData()
{
return this.data;
}
public void setKeyIndex(int indx)
{
this.keyIndx = indx;
}
public int getKeyIndx()
{
return this.keyIndx;
}
}