简单的过期缓存

原创
2019/06/11 13:42
阅读数 94
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");

 

展开阅读全文
加载中

作者的其它热门文章

打赏
0
0 收藏
分享
打赏
0 评论
0 收藏
0
分享
返回顶部
顶部