Java三个类实现内存缓存

来源:互联网 发布:商业组织域名代码 编辑:程序博客网 时间:2024/06/04 19:28

有一个需求,本来打算用redis来做,但是发现redis的list不支持某一项超时设置,

所以就用java自己写了一个简单的缓存,操作类似redis,总共只有3个类:

项目地址:https://github.com/newpanjing/group-cache.git

项目名:group-cache

简单的内存缓存实现,实现group概念,一个group里面是个有序的集合,集合支持key-value expire弥补redis list的不足

总共有3个类:

GroupCacheFactory 工厂用于获取Group
Group 组,存放多个key和value
CacheEntity 缓存实体,所有缓存的数据都是以CacheEntity为载体放入Group中

测试代码:

package com.qikenet.cache;import java.util.Random;public class CacheTest {public static void main(String[] args) {    /**     * 概念:     * 组缓存,在传统redis、memcached 这一类的缓存容器中,都是key-value类型的     * 所谓的组缓存,就是在key-value的外层加一个标识     * 用list来做比较,在redis中,list的结构是这样的,并且list的某一项不能设置存活时间:     *  abc     *      1     *      2     *      3     *      * 在GroupCache中结构是这样的   :     * abc     *  a 1 10     *  b 2 5     *  c 3 1     * 第一行:a代表key,1代表value,10代表存活10秒,存活时间以秒为单位              */    //创建一个工厂,暂时不支持持久化    GroupCacheFactory factory=new GroupCacheFactory();    //获取一个组    Group group1=factory.group("group1");    group1.push("a", 123);//默认永久存活    group1.push("b", 321, 10);//存活10秒    //查看还有多久失效    System.out.println("group 1 的元素b 剩余失效时间:"+group1.ttl("b"));    //检测值是否存在    System.out.println("a是否存在:"+group1.exist("a"));    System.out.println("c是否存在:"+group1.exist("c"));    //获取有效的key    System.out.println("group1 keys:"+group1.getKeys());    //获取有效的value    System.out.println("group1 values:"+group1.getValues());    //通过key获取值    System.out.println("通过a获取:"+group1.getValue("a"));    //获取一个组,并设置容量为100,默认容量为1000,不同的group中数据不能共享    Group group2=factory.group("group2",100);    //如果push的数据大于容量,则会丢弃    for(int i=0;i<101;i++){        group2.push(String.valueOf(i), i, new Random().nextInt(10));    }    //获取存活的元素的数量    System.out.println("group2大小:"+group2.size());    //设置元素的存活时间    group2.expire("2", 100);    //删除一个元素    group2.delete("3");    System.out.println("group删除后的元素大小:"+group2.size());    //获取group容量大小    System.out.println("group2容量:"+group2.getCapacity());    System.out.println(group2.getKeys());}}



具体代码:

缓存工厂:

package com.qikenet.cache;import java.util.LinkedHashMap;import java.util.Map;import java.util.Random;/** * 简单的内存缓存实现,实现group概念,<br/> * 一个group里面是个有序的集合,<br/> * 集合支持key-value expire弥补redis list的不足 *  * @author panjing * @date 2016年8月6日 上午9:27:22 * @project qikenet-group-cache */public class GroupCacheFactory {// 数据容器private Map<String, Object> container;public GroupCacheFactory() {container = new LinkedHashMap<String, Object>();}/** * 如果组存在就返回,不存在就创建,保证不为null *  * @param key * @return */public Group group(String key, int capacity) {Group group = null;Object entry = container.get(key);if (entry != null) {group = (Group) entry;} else {group = new Group(capacity);container.put(key, group);}return group;}/** * 如果组存在就返回,不存在就创建,默认容量1000 *  * @param key * @return */public Group group(String key) {return this.group(key, 1000);}}

缓存Group:

package com.qikenet.cache;import java.util.ArrayList;import java.util.Iterator;import java.util.List;import java.util.concurrent.ArrayBlockingQueue;/** * 组操作,内部数据有序队列 *  * @author panjing * @date 2016年8月6日 上午9:33:34 * @project qikenet-group-cache * @param <T> */public class Group {private ArrayBlockingQueue<CacheEntity> queue;// 缓存队列private Integer capacity;public Group(int capacity) {queue = new ArrayBlockingQueue<CacheEntity>(capacity);this.capacity = capacity;}/** * 尾部进 *  * @param object * @param second */public void push(String key, Object object, int second) {// 放入队列,queue.offer(new CacheEntity(key, object, System.currentTimeMillis(), second, this));}/** * 尾部进 *  * @param object */public void push(String key, Object object) {push(key, object, 0);}/** * 返回并移除头部出 *  * @return */public Object poll() {CacheEntity entity = queue.poll();// 如果有效期超过,返回nullif (!entity.isExpire()) {return null;}return entity.getValue();}/** * 返回头部元素并放到末尾 *  * @return */public Object rPoll() {CacheEntity entity = queue.poll();// 如果有效期超过,返回nullif (!entity.isExpire()) {return null;}Object object = entity.getValue();queue.offer(entity);return object;}/** * 通过key寻找有效的缓存实体 *  * @param key * @return */private CacheEntity find(String key) {synchronized (queue) {Iterator<CacheEntity> iterator = queue.iterator();while (iterator.hasNext()) {CacheEntity entity = iterator.next();if (key.equals(entity.getKey())) {return entity;}}return null;}}/** * 删除key *  * @param key */public void delete(String key) {synchronized (queue) {CacheEntity entity = find(key);if (entity != null) {queue.remove(entity);}}}/** * 根据key获取 *  * @param key * @return */public Object getValue(String key) {CacheEntity entity = find(key);if (entity != null && entity.isExpire()) {return entity.getValue();}return null;}/** * 获取有效的缓存实体 *  * @return */private List<CacheEntity> getCacheEntitys() {List<CacheEntity> keys = new ArrayList<CacheEntity>();Iterator<CacheEntity> iterator = queue.iterator();while (iterator.hasNext()) {CacheEntity cacheEntity = iterator.next();if (cacheEntity.isExpire()) {keys.add(cacheEntity);}}return keys;}/** * 获取key列表 *  * @return */public List<String> getKeys() {List<String> keys = new ArrayList<String>();List<CacheEntity> caches = getCacheEntitys();for (CacheEntity cacheEntity : caches) {keys.add(cacheEntity.getKey());}return keys;}/** * 获取值列表 *  * @return */public List<Object> getValues() {List<Object> values = new ArrayList<Object>();List<CacheEntity> caches = getCacheEntitys();for (CacheEntity cacheEntity : caches) {values.add(cacheEntity.getValue());}return values;}/** * 查看元素存活时间,-1 失效,0 长期有效 *  * @param key * @return */public int ttl(String key) {CacheEntity entity = find(key);if (entity != null) {return entity.ttl();}return -1;}/** * 返回头部的元素 *  * @return */public Object peek() {CacheEntity entity = queue.peek();if (entity != null) {return entity.getValue();}return null;}/** * 设置元素存活时间 *  * @param key * @param second */public void expire(String key, int second) {CacheEntity entity = find(key);if (entity != null) {entity.setTimestamp(System.currentTimeMillis());entity.setExpire(second);}}/** * 查看key是否存在 *  * @param key * @return */public boolean exist(String key) {return find(key) != null;}/** * 查看组是否为空 *  * @return */public boolean isEmpty() {return queue.isEmpty();}/** * 获取存活元素的大小 *  * @return */public int size() {return getCacheEntitys().size();}/** * 获取容量 *  * @return */public Integer getCapacity() {return capacity;}}
缓存实体:

package com.qikenet.cache;import java.io.Serializable;/** * 缓存实体 *  * @author panjing * @date 2016年8月6日 上午9:33:25 * @project qikenet-group-cache */public class CacheEntity implements Serializable {private static final long serialVersionUID = 2082223810638865724L;private String key; // keyprivate Object value;// 值private Long timestamp;// 缓存的时候存的时间戳,用来计算该元素是否过期private int expire = 0; // 默认长期有效private Group group;// 容器public CacheEntity(String key, Object value, Long timestamp, int expire, Group group) {super();this.key = key;this.value = value;this.timestamp = timestamp;this.expire = expire;this.group = group;}public void setTimestamp(Long timestamp) {this.timestamp = timestamp;}public Long getTimestamp() {return timestamp;}public String getKey() {return key;}public void setKey(String key) {this.key = key;}public Object getValue() {return value;}public void setValue(Object value) {this.value = value;}public int getExpire() {return expire;}public void setExpire(int expire) {this.expire = expire;}/** * 获取剩余时间 *  * @return */public int ttl() {if (this.expire == 0) {return this.expire;}return this.expire - getTime();}/** * 获取当前时间和元素的相差时间 * @return */private int getTime() {if (this.expire == 0) {return this.expire;}Long current = System.currentTimeMillis();Long value = current - this.timestamp;return (int) (value / 1000) + 1;}/** * 是否到期 *  * @return */public boolean isExpire() {if (this.expire == 0) {return true;}if (getTime() > this.expire) {// 失效了就移除group.delete(key);return false;}return true;}}



0 0
原创粉丝点击