前言
我们都知道为了减轻数据库的访问压力,有一个很好的办法就是添加本地缓存或者分布式缓存,那么大家了解缓存都有哪几种算法吗?我为大家介绍其中的一种算法——FIFO先进先出算法!
一、FIFO算法是什么?
FIFO先进先出算法其原理是,当缓存容器满了的时候想要插入一条新的对象,那么我们不得不删除最前面的那个对象,循环罔替。我们先来看是怎么实现的,最后我来告诉大家这种算法的不足之处!
二、使用步骤
1.先写一个接口类
在写FIFO(先进先出)缓存算法之前,我们先来拿个先案例简单实现一下缓存Cache。
代码如下(示例):
public interface Cache{
void putObject(Object key,Object value);
Object getObjec(key,value);
Object removeObjec(key,value);
void clear();
int size();
}
2.简单的Cache实现类
代码如下(示例):
/**
* 简易Cache实现
* 1)存储结构:散列表(基于JAVA中的hashmap存储)
* 2)淘汰算法:没有(直到到内存溢出)
* 3)线程安全:否
* 4)缓存对对象的引用?强引用
* 5)对象获取:浅拷贝(获取对象地址)
*/
public class perpetualCache implements Cache(){
private HashMap<Object,Object> cache=new HashMap<>();
@Override
public void putObject(Object key, Object value) {
cache.put(key, value);
}
@Override
public Object getObject(Object key) {
return cache.get(key);
}
@Override
public Object removeObject(Object key) {
return cache.remove(key);
}
@Override
public void clear() {
cache.clear();
}
@Override
public int size() {
return cache.size();
}
@Override
public String toString() {
return "PerpetualCache{" +
"cache=" + cache.toString() +
'}';
}
}
下面我们把这个类作为基础去拓展FIFO算法,代码如下:
3.FIFO算法实现
/**
* 构建先进先出Cache对象:缓存满了以后要优先淘汰最早放入的对象
* 1)存储数据:基于hashmap
* 2)淘汰算法:FIFO(关键点在于如何记录key的添加顺序)
*
*/
public class FifoCache implements Cache{
/**关联Cache对象-找到可以存储数据的基层对象*/
private Cache cache;
/**定义Cache的最大容量*/
private int maxCap;
/**通过队列记录key的添加顺序,Deque是JAVA中的双端队列*/
private Deque<Object> keyOrders;
public FifoCache(Cache cache, int maxCap) {
this.cache = cache;
this.maxCap = maxCap;
this.keyOrders=new LinkedList<>();
}
@Override
public void putObject(Object key, Object value) {
//1.记录key的顺序(添加在队列的尾部)
keyOrders.addLast(key);
//2.判断容器是否已满,满了则移除
if(keyOrders.size()>maxCap){
Object firstKey = keyOrders.removeFirst();
//从cache中清除指定key对应的对象
cache.removeObject(firstKey);
}
//3.向cache添加数据
cache.putObject(key, value);
}
@Override
public Object getObject(Object key) {
return cache.getObject(key);
}
@Override
public Object removeObject(Object key) {
//1.从Cache中移除对象
Object object = cache.removeObject(key);
//2.从队列移除key
keyOrders.remove(key);
return object;
}
@Override
public void clear() {
cache.clear();
keyOrders.clear();
}
@Override
public int size() {
return cache.size();
}
@Override
public String toString() {
return "FifoCache{" +
"cache=" + cache.toString() +
", maxCap=" + maxCap +
", keyOrders=" + keyOrders +
'}';
}
public static void main(String[] args) {
Cache cache=new FifoCache(//负责添加算法
new PerpetualCache(),//负责存数据
3);
//如上语句其实是一种装饰模式的实现(思考:new BufferedReader(new FileReader(file)))
cache.putObject("A", 100);
cache.putObject("B", 200);
cache.putObject("C", 300);
cache.putObject("D", 400);
cache.putObject("E", 500);
System.out.println(cache);
}
}
4. 运行效果
可以看出,最后就只剩C,D,E,A和B都被删除掉了!
总结
这种算法的缺点在于:FIFO算法对于一些内存中访问频率比较高,但是放入的时间又比较早的对象而言,命中率会比较率。所以这种算法使用的越来越少了,近些年比较流行的缓存算法为Lru算法,等我完全吃透Lru算法再来为大家讲解哦!