缓存架构
package com.mldn.demo;
import java.util.Map;
import java.util.concurrent.*;
class News {
private Long id ;
private String title ;
public News(Long id,String title){
this.id = id ;
this.title = title ;
}
@Override
public String toString() {
return "新闻ID:"+this.id+"、新闻内容:"+this.title;
}
}
/**
*进行缓存操作的实现类,可以进行指定数据的存储
* @param <K> 描述缓存key数据类型,此类型一定是唯一的,可以方便查询的(数据库的缓存ID是唯一的)
* @param <V> 描述进行数据缓存的内容项(VO类)
*/
class Cache<K,V> {
private static final TimeUnit TIME = TimeUnit.SECONDS ;
private static final long DELAY_SECOND = 2 ;//默认数据的缓存时间为2秒
private Map<K,V> cacheObjects = new ConcurrentHashMap<>() ;//该缓存类型可以进行并发控制
private BlockingQueue<DelavedItem<Pair>> queue = new DelayQueue<>();//定义阻塞队列
//进行后台线程的启动
public Cache(){
Thread deamonThread = new Thread(()->{
while (true){//不断等待队列弹出的数据
try {
DelavedItem<Pair> item = Cache.this.queue.take() ;//获取队列中的数据
if(item !=null){//此时有数据进行弹出
Pair pair = item.getItem() ;//获取包装了当前KV的对象
Cache.this.cacheObjects.remove(pair.key,pair.value);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
},"后台队列清理线程") ;
deamonThread.setDaemon(true);//设置为后台线程
deamonThread.start();//线程启动
}
public void put(K key,V value)throws Exception{
//一旦数据进行存放的时候,该数据有可能已经在队列中存在了,也有可能不存在
// 如果数据在队列中存在,那么就可以将原始队列中的数据删除掉(避免重复)
// 如果数据本身不在队列中,就将数据直接保存在队列中。
V oldValue = this.cacheObjects.put(key,value) ;//数据保存同时返回原始旧数据
if(oldValue !=null){//该key的数据之前已经存放过了
this.queue.remove(oldValue) ;
}
this.queue.put(new DelavedItem<Pair>(new Pair(key,value),DELAY_SECOND,TIME));
}
public V get(K key){
return this.cacheObjects.get(key) ;
}
//实现阻塞队列中要进行的数据封装
private class Pair{
private K key ;
private V value ;
public Pair(K key, V value) {
this.key = key;
this.value = value;
}
}
//进行延迟队列的操作控制
private class DelavedItem<T> implements Delayed{
private T item ; //延迟队列缓存项
private long delay ;//延迟时间
private long expire ;//失效时间
public DelavedItem(T item,long delay,TimeUnit time){
this.item = item ;//设置真实的操作数据
this.delay = TimeUnit.MILLISECONDS.convert(delay,time) ;//以毫秒为单位进行控制
this.expire = this.delay + System.currentTimeMillis() ;//设置失效时间
}
@Override
public long getDelay(TimeUnit unit) {
return unit.convert(this.expire - System.currentTimeMillis(),TimeUnit.MILLISECONDS);
}
@Override
public int compareTo(Delayed o) {
return (int) (this.delay-this.getDelay(TimeUnit.MILLISECONDS));
}
public T getItem() {
return item;
}
}
}
public class JUUCDemo {
public static void main(String[] args) throws Exception{
Cache<Long,News> cache = new Cache<>() ;//后台线程启动了
cache.put(0L,new News(0L,"熊二"));
cache.put(1L,new News(1L,"张三"));
cache.put(2L,new News(2L,"李四"));
cache.put(3L,new News(3L,"王五"));
cache.put(4L,new News(4L,"赵六"));
cache.put(5L,new News(5L,"李七"));
cache.put(6L,new News(6L,"朱八"));
cache.put(7L,new News(7L,"童九"));
System.out.println(cache.get(1l));
TimeUnit.MILLISECONDS.sleep(1000);
cache.put(1L,new News(1L,"张三"));
TimeUnit.MILLISECONDS.sleep(2000);
System.out.println(cache.get(1l));
}
}