com.eshore.khala.utils.LRUCache Maven / Gradle / Ivy
package com.eshore.khala.utils;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
/**
* LRU 缓存
* 实现按访问的时间,保留最近访问的缓存方案
*
* @author eric
*
* 2017-07-12
*
* @param 键
* @param 值
*/
public class LRUCache implements Cache {
static ExecutorService fixedThreadPool = Executors.newFixedThreadPool(1);
/**
* 回收过时数据
* @param cache
*/
public static void addWacher(final LRUCache cache){
fixedThreadPool.submit(new Callable(){
@Override
public Object call() throws Exception {
cache.recycle();
//System.out.println("======================================");
return null;
}
});
}
/**
* 回收频率
*/
private long recycleTime=600;
private int recycleFrequency=500;
int count=0;
long last =System.currentTimeMillis();
private void count(){
/*if(count++>recycleFrequency){
count=0;
addWacher(this);
}*/
if(System.currentTimeMillis()-last>recycleTime){
addWacher(this);
last=System.currentTimeMillis();
}
}
/**
* 最大的缓存个数,超出的按最后的访问时算保留最近访问的
*/
private int maxSize = 65535;
/**
* 缓存时长,为0时没有时间限制
*/
private long cacheTime =60*1000*60*2;
/**
* 缓存的元素个数
*/
private int size;
/**
* 缓存MAP
*/
private Map> cache;
CacheNode head;
CacheNode tail;
/**
* 设置缓存时长,单位为毫秒
* @param ms
*/
public void setCacheTime(long ms){
cacheTime=ms;
}
/**
* 获取默认缓存时长
* @return
*/
public long getCacheTime(){
return cacheTime;
}
/**
* 获取元素个数
* @return
*/
public int size() {
return size;
}
/**
*
* @param maxSize 最大的缓存个数
*/
public LRUCache(int maxSize) {
this.maxSize = maxSize;
//cache = new TreeMap>();
cache = new HashMap>(maxSize);
}
/**
*
* @param maxSize 最大的缓个数
* @param time 缓存时长 单位:毫秒 为0时长久有效
*/
public LRUCache(int maxSize,long time) {
this(maxSize);
setCacheTime(time);
}
/**
* 默认构造器,默认缓存个数65535 ,缓存时长为0即不计算时长
*
*/
public LRUCache() {
cache = new HashMap>(maxSize);
}
/**
* 增加元素到缓存中
* @param k key 键
* @param v value 值
*/
public void put(K k, V v) {
put(k,v,cacheTime);
}
/**
* 增加元素到缓存中
* @param k key 键
* @param v value 值
* @param time 缓存时长 0则不算
*/
@SuppressWarnings("unchecked")
public synchronized void put(K k, V v,long time) {
count();
if (head == null) {
tail = new CacheNode(k, v,time);
head = tail;
tail.pre = head;
cache.put(k, head);
size++;
return;
}
if (cache.containsKey(k)) {
CacheNode n = cache.get(k);
n.setValue(v);
n.updateTime();
n.setCacheTime(time);
n.setRemoved(false);
if (n != null && n == head) {
// System.out.println(n);
return;
}
if (n == tail) {
tail = tail.pre;
// System.out.println("uuuuuuuu="+k);
}
n.remove();
head.appendTo(n);
// n.insertBefore(head);
if (n.pre == null && n.next == null)
throw new RuntimeException("000000");
if (tail.pre == null && tail.next == null)
throw new RuntimeException("000tail000:" + k + " tail:"
+ tail.key);
// head.appendTo(n);
head = n;
return;
}
if (size >= maxSize) {
// if((Integer)k==99)System.out.println("==0000000000==="+tail.key);
CacheNode n = new CacheNode(k, v,time);
head.appendTo(n);
head = n;
cache.put(k, n);
// System.out.println("==remove==="+tail.key+"----"+k);
cache.remove(tail.getKey());
CacheNode ot = tail;
if (tail != null) {
tail = tail.pre;
if (tail == null) {
//System.out.println("==" + ot.key);
}else{
tail.next = null;
}
// ot.remove();
} else {
//System.out.println(k);
}
if (n.pre == null && n.next == null)
throw new RuntimeException("0000==00");
return;
}
{
CacheNode n = new CacheNode(k, v,time);
head.appendTo(n);
head = n;
cache.put(k, n);
size++;
}
}
/**
* 获取缓存值
* @param k
* @return value
*/
public V get(K k) {
CacheNode n = cache.get(k);
if (n == null)
return null;
return n.getValue();
}
/**
* 获取所有的key
* @return keys
*/
public Collection keys() {
return cache.keySet();
}
/**
* 获取所有的值
* @return
*/
public Collection values() {
ArrayList al = new ArrayList();
CacheNode flag = head;
while (flag != null) {
if(!flag.isExpire())
al.add(flag.getValue());
flag = flag.next;
if (flag == head)break;
//throw new RuntimeException("reply!");
}
return al;
}
public Collection> nodes() {
ArrayList> al = new ArrayList>();
CacheNode flag = tail;
while (flag != null) {
if(!flag.isExpire()){
al.add(flag);
}else{
flag.value=null;
flag.setRemoved(true);
}
flag = flag.pre;
if (flag == tail)break;
//throw new RuntimeException("reply!");
}
return al;
}
@Override
public V remove(K k) {
// TODO Auto-generated method stub
CacheNode n = cache.get(k);
if(n==null)return null;
V v=n.getValue();
n.setRemoved(true);
n.setValue(null);
//n.
return v;
}
@Override
public boolean containsKey(Object key) {
// TODO Auto-generated method stub
CacheNode n = cache.get(key);
if(n==null)return false;
if(n.isExpire()||n.isRemoved())return false;
return true;
}
/**
* 回收超时的
*/
public void recycle(){
try{
Collection> nodes = this.nodes();
if(nodes!=null)
for(CacheNode n :nodes){
if(n.isExpire()){
n.setRemoved(true);
n.setValue(null);
//System.out.println("*************************"+n.key);
}
}
}catch(Throwable t){
t.printStackTrace();
}
}
public int getRecycleFrequency() {
return recycleFrequency;
}
public void setRecycleFrequency(int recycleFrequency) {
this.recycleFrequency = recycleFrequency;
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy