您的位置:首页 > 其它

通过ConcurrentHashMap实现本地缓存

2017-03-19 10:04 113 查看
在做项目的时候,往往遇到需要使用缓存,但是缓存的量不大,没有必要使用redis这样的缓存。比如我做一个定时任务,捞取从什么时间之后需要发货的订单,想要把这个时间点做一个配置,所以自己使用ConcurrentHashMap实现了一个简单的缓存

package cahche;

import java.util.Calendar;
import java.util.Date;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

public class StaticCache {

    private static Map<String, Element> map = new ConcurrentHashMap<>();
    
    /**
     * @Desc
     * @Date 2017年3月19日上午10:19:40
     * @param key 缓存key
     * @param value 缓存value
     * @param expireTime 缓存过期时间(秒)
     */
    public static void set(String key, String value, int expireTime){
        Date expireDate = CalculateSecondTimeInterval(new Date(), expireTime) ;
        map.put(key, new Element(value, expireDate));
        
    }
    
    /**
     * @Desc
     * @Date 2017年3月19日上午10:20:26
     * @param key 缓存key
     * @return
     */
    public static String get(String key){
        if(map.containsKey(key) && map.get(key).getExpireDate().after(new Date())){
            return map.get(key).getValue();
        }
        return null;
    }
    
    private static Date CalculateSecondTimeInterval(Date baseDate,int timeDiff){
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(baseDate);
        calendar.add(Calendar.SECOND, timeDiff);
        return calendar.getTime();
    }
    
}

class Element{
    
    private String value;
    
    private Date expireDate;
    
    public Element(String value, Date expireDate) {
        super();
        this.value = value;
        this.expireDate = expireDate;
    }
    
    public String getValue() {
        return value;
    }
    
    public void setValue(String value) {
        this.value = value;
    }
    
    public Date getExpireDate() {
        return expireDate;
    }
    
    public void setExpireDate(Date expireDate) {
        this.expireDate = expireDate;
    }
    
}

测试代码:
package cahche;

public class TestCache{

private final static String QUERY_DELIVERY_DAY_KEY = "query.delivery.days";
public static void main(String[] args) throws InterruptedException {
if(StaticCache.get(QUERY_DELIVERY_DAY_KEY) == null){

//直接查询配置
String day = "30";

//更新缓存,设置缓存失效时间为60s
StaticCache.set(QUERY_DELIVERY_DAY_KEY, day, 3);

System.out.println("缓存设置成功");
}

System.out.println("获取query.delivery.days的值:" + StaticCache.get(QUERY_DELIVERY_DAY_KEY));

//等待3s
Thread.sleep(3*1000);

System.out.println("3s后获取query.delivery.days的值:" + StaticCache.get(QUERY_DELIVERY_DAY_KEY));
}
}
结果:

缓存设置成功

获取query.delivery.days的值:30

3s后获取query.delivery.days的值:null

需要注意几点:

1、在多线程环境下不能使用HashMap,原因是在多线程put的时候可能出现元素丢失的情况,更严重的是在HashMap  reHash时可能会出现死循环的链表,导致get操作一直循环下去,造成CPU被打满的情况

2、由于static所指向的全局变量在GC的时候作为GC Root不会被回收掉,从而整个map中的元素都不能被GC掉,当整个map的元素过多的时候,会导致堆内存溢出。这种方案只适合用于小数量的缓存

参考:https://my.oschina.net/xianggao/blog/393990
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: