import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.*;
/**
* 简单的过期缓存仓库
* 数据放在以1秒为单位的时间桶里,时间桶的时间表示过期时间
*/
public class SimpleExpireCache {
private static final Logger logger = LoggerFactory.getLogger(SimpleExpireCache.class);
/**
* 缓存仓库名称
*/
private String cacheName;
/**
* 过期秒数
*/
private int expireSeconds;
/**
* 缓存存储
*/
private List<SimpleExpireCacheBucket> buckets;
/**
* 构造函数
* @param name
* @param expireSeconds
*/
public SimpleExpireCache(String name, int expireSeconds){
this.cacheName = name;
this.expireSeconds = expireSeconds;
this.buckets = new LinkedList<>();
}
/**
* 添加到缓存,并清理过期缓存,事务
* @param key
*/
public void add(String key){
synchronized (buckets){
_clearExpired();
_add(key);
}
}
/**
* 是否存在某个未过期的键,事务
*/
public boolean containsNotExpiredKey(String key){
synchronized (buckets){
_clearExpired();
return _containsNotExpiredKey(key);
}
}
/**
* 检查没有再添加,事务
* @param key
* @return
*/
public boolean checkAndAdd(String key){
synchronized (buckets){
_clearExpired();
if(_containsNotExpiredKey(key)){
return false;
}else{
_add(key);
return true;
}
}
}
/**
* 清理过期缓存
*/
private void _clearExpired(){
Iterator<SimpleExpireCacheBucket> iter = buckets.iterator();
while(iter.hasNext()){
SimpleExpireCacheBucket bucket = iter.next();
Date expireDate = bucket.getExpireDate();
Date now = new Date();
if(now.after(expireDate)){
iter.remove();
}
}
}
/**
* 添加
* @param key
*/
private void _add(String key){
Date now = new Date();
Calendar cal = Calendar.getInstance();
cal.setTime(now);
cal.set(Calendar.MILLISECOND, 0);
cal.add(Calendar.SECOND, this.expireSeconds+1);
Date expireDate = cal.getTime();
// find bucket
SimpleExpireCacheBucket bucket = _getBucket(expireDate);
if(null == bucket){
// if no bucket
bucket = new SimpleExpireCacheBucket(expireDate);
buckets.add(bucket);
}
bucket.add(key);
}
/**
* 是否存在未过期的键
* @param key
* @return
*/
private boolean _containsNotExpiredKey(String key){
Iterator<SimpleExpireCacheBucket> iter = buckets.iterator();
while(iter.hasNext()){
SimpleExpireCacheBucket bucket = iter.next();
Date expireDate = bucket.getExpireDate();
Date now = new Date();
if(now.after(expireDate)){
continue;
}else{
if(bucket.contains(key)){
return true;
}
}
}
return false;
}
/**
* 获取包含某个时间的数据桶
* @param date
* @return
*/
private SimpleExpireCacheBucket _getBucket(Date date){
Iterator<SimpleExpireCacheBucket> iter = buckets.iterator();
while(iter.hasNext()){
SimpleExpireCacheBucket bucket = iter.next();
Date dateTo = bucket.getExpireDate();
Calendar cal = Calendar.getInstance();
cal.setTime(dateTo);
cal.add(Calendar.SECOND, -1);
Date dateFrom = cal.getTime();
if(date.getTime() > dateFrom.getTime() && date.getTime() <= dateTo.getTime()){
return bucket;
}
}
return null;
}
}
/**
* 某个1秒内过期的数据桶
* 时间表示过期时间
*/
class SimpleExpireCacheBucket{
private Date expireDate;
private Set<String> set;
public SimpleExpireCacheBucket(Date expireDate){
this.expireDate = expireDate;
this.set = new HashSet<>();
}
public Date getExpireDate(){
return this.expireDate;
}
public void add(String key){
this.set.add(key);
}
public boolean contains(String key){
return set.contains(key);
}
}
使用方法:
SimpleExpireCache cache = new SimpleExpireCache("name", 5);
cache.add("key");
cache.checkAndAdd("key");
cache.containsNotExpiredKey("key");