栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

08-Java中本地缓存实现(拓展练习)

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

08-Java中本地缓存实现(拓展练习)

文章目录
  • 简介
    • 为什么要Cache
    • 你都了解哪些Cache?
    • 对本地缓存你会如何设计
  • 本地缓存的设计
    • Cache接口设计
    • Cache默认存储设计
    • SynchronizedCache 设计及实现
    • LoggingCache 设计及实现
    • FifoCache设计及实现
    • LruCache 设计及实现
  • 总结(Summary)

简介 为什么要Cache
  • 降低数据库的访问压力.
  • 提高查询的性能,改善用户体验.
你都了解哪些Cache?
  • 浏览器缓存
  • 数据持久层的Cache(MyBatis中的Cache设计)
  • 逻辑处理层的Cache(Spring中的Cache)
  • CPU的高速缓存
对本地缓存你会如何设计
  • 数据的存储结构(散列存储)
  • 数据的淘汰算法(FIFO,LRU)
  • 任务调度策略(定时刷新缓存)
  • 缓存日志的记录(命中率)
  • GC时会缓存数据的影响
本地缓存的设计 Cache接口设计

我们在设计Cache时,一般会先设计一个接口,定义一套规范,例如:

package com.jt.cache;


public interface Cache {
    
    void putObject(Object key,Object value);

    
    Object getObject(Object key);

    
    Object removeObject(Object key);

    
    void clear();

    
    int size();
    //...
}
Cache默认存储设计

设计一个Cache的默认存储对象,主要用于存储数据,例如:

package com.jt.cache;

import java.util.HashMap;
import java.util.Map;

public class DefaultCache implements  Cache{
    private Map 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 "DefaultCache{" +
                "cache=" + cache.toString() +
                '}';
    }

    public static void main(String[] args) {
        Cache cache=new DefaultCache();
        cache.putObject("A",100);
        cache.putObject("B",200);
        cache.putObject("C",300);
        System.out.println(cache);
    }
}
SynchronizedCache 设计及实现

线程安全的Cache设计及实现,例如:

package com.jt.cache;

public class SynchronizedCache implements Cache {
    private Cache cache;

    public SynchronizedCache(Cache cache) {
        this.cache = cache;
    }

    @Override
    public synchronized void putObject(Object key, Object value) {
        cache.putObject(key, value);
    }

    @Override
    public synchronized Object getObject(Object key) {
        return cache.getObject(key);
    }

    @Override
    public synchronized Object removeObject(Object key) {
        return cache.removeObject(key);
    }

    @Override
    public void clear() {
        cache.clear();
    }

    @Override
    public int size() {
        return cache.size();
    }

    @Override
    public String toString() {
        return "SynchronizedCache{" +
                "cache=" + cache +
                '}';
    }

    public static void main(String[] args) {
        Cache cache = new SynchronizedCache(new DefaultCache());
        cache.putObject("A", 100);
        cache.putObject("B", 200);
        System.out.println(cache);
    }
}
LoggingCache 设计及实现

实际工作中我们经常要分析和监控缓存的命中率,例如我们设计了缓存,但为什么还是查询了数据库,有多少请求数据来自缓存,多少请求查询了数据库等,此时需要一个基于日志进行分析的一个过程,因此LoggingCache对象诞生,例如:

package com.jt.cache;


public class LoggingCache implements Cache{
    
    private Cache cache;
    
    private int requests;
    
    private int hints;
    public LoggingCache(Cache cache){
        this.cache=cache;
    }

    @Override
    public void putObject(Object key, Object value) {
         cache.putObject(key,value);
    }
    @Override
    public Object getObject(Object key) {
        //1.记录请求次数
        requests++;
        //2.从cache获取数据
        Object object = cache.getObject(key);
        if(object!=null){
            //计算命中率
            hints++;
            System.out.println("hits/requests is "+hints*1.0/requests);
        }
        return object;
    }
    @Override
    public Object removeObject(Object key) {
        return cache.removeObject(key);
    }

    @Override
    public void clear() {
       cache.clear();
    }
    @Override
    public int size() {
        return cache.size();
    }

    public static void main(String[] args) {
        LoggingCache loggingCache =
                new LoggingCache(new DefaultCache());
        loggingCache.putObject("A",100);
        loggingCache.putObject("B",200);
        loggingCache.putObject("C",300);
        loggingCache.getObject("D");
        loggingCache.getObject("A");
        loggingCache.getObject("A");
    }
}
FifoCache设计及实现

缓存可以提供的内存空间是有限的,在缓存满的时候,我们要提供一些数据淘汰策略,接下来我们基于FIFO算法,对缓存进行设计,例如:

package com.jt.cache;

import java.util.Deque;
import java.util.linkedList;


public class FifoCache implements Cache{
    
    private Cache cache;
    
    private int maxCap;
    
    private Deque deque;
    public FifoCache(Cache cache, int maxCap) {
        this.cache = cache;
        this.maxCap = maxCap;
        this.deque=new linkedList<>();
    }
    @Override
    public void putObject(Object key, Object value) {
        //1.记录key的顺序
        deque.addLast(key);
        //2.判定cache是否已满,满了则移除元素
        //if(cache.size()==maxCap){} 方式1
        if(deque.size()>maxCap){//方式2
            //获取最先放入的元素key
            Object eldestKey=deque.removeFirst();
            //移除最先放进去的元素
            cache.removeObject(eldestKey);
        }
        //3.添加新的元素
        cache.putObject(key,value);
    }
    @Override
    public Object getObject(Object key) {
        return cache.getObject(key);
    }

    @Override
    public Object removeObject(Object key) {
        Object value=cache.removeObject(key);
        deque.remove(key);
        return value;
    }

    @Override
    public void clear() {
        cache.clear();
        deque.clear();
    }

    @Override
    public int size() {
        return cache.size();
    }

    @Override
    public String toString() {
        return "FifoCache{" +
                "cache=" + cache +
                '}';
    }

    public static void main(String[] args) {
        FifoCache cache = new FifoCache(new DefaultCache(), 3);
        cache.putObject("A",100);
        cache.putObject("B",200);
        cache.putObject("C",300);
        cache.putObject("D",400);
        cache.putObject("E",500);
        System.out.println(cache);
    }
}
 
LruCache 设计及实现 

基于LRU算法(最近最少使用算法)对缓存进行数据淘汰设计,例如:

package com.cy.java.cache;  
import java.util.linkedHashMap;  
import java.util.Map;  
  
  
public class LruCache implements Cache {  
 private Cache cache;  
   
 private Object eldestKey;  
   
 private Map keyMap;  
 @SuppressWarnings("serial")  
 public LruCache(Cache cache,int maxCap) {  
 this.cache=cache;  
//linkedHashMap可以记录key的添加顺序或者访问顺序  
 this.keyMap=new linkedHashMap(maxCap, 0.75f, true)
 {//accessOrder  
//此方法每次执行keyMap的put操作时调用  
@Override  
protected boolean removeEldestEntry (java.util.Map.Entry eldest) {  
boolean isFull=size()>maxCap;  
if(isFull)eldestKey=eldest.getKey();  
return isFull;  
}  
 };  
}  
@Override  
public void putObject(Object key, Object value) {  
//存储数据对象  
cache.putObject(key, value);  
//记录key的访问顺序,假如已经满了,就要从cache中移除数据  
keyMap.put(key, key);//此时会执行keyMap对象的removeEldestEntry  
if(eldestKey!=null) {  
cache.removeObject(eldestKey);  
eldestKey=null;  
}  
}  
@Override  
public Object getObject(Object key) {  
keyMap.get(key);//记录key的访问顺序  
return cache.getObject(key);  
}  
  
@Override  
public Object removeObject(Object key) {  
return cache.removeObject(key);  
}  
  
@Override  
public void clear() {  
cache.clear();  
keyMap.clear();  
}  
@Override  
public int size() {  
return cache.size();  
}  
@Override  
public String toString() {  
return cache.toString();  
}  
  
public static void main(String[] args) {  
SynchronizedCache cache=  
 new SynchronizedCache(  
new LoggingCache(  
new LruCache(new PerpetualCache(),3)));  
cache.putObject("A", 100);  
cache.putObject("B", 200);  
cache.putObject("C", 300);  
cache.getObject("A");  
cache.getObject("C");  
cache.putObject("D", 400);  
cache.putObject("E", 500);  
System.out.println(cache);  
  
}  
}
总结(Summary)

本章节为基础拓展章节,重点是通过本地缓存的设计,加强Java中一些基础点的理解,同时在Java缓存设计上做一个拔高.

转载请注明:文章转载自 www.mshxw.com
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号