文档章节

Guava Cache

山东和湖北
 山东和湖北
发布于 2016/05/11 18:01
字数 889
阅读 75
收藏 0
package guavaCache;

import com.google.common.base.Equivalence;
import com.google.common.base.Joiner;
import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheStats;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.InitializingBean;

import java.util.*;
import java.util.concurrent.ConcurrentHashMap;

/**
 * User: zhaoyun
 * Date: 16-5-11
 * Time: 下午5:09
 */
public class GuavaCache implements InitializingBean {

    /**
     * 日志器
     */
    private final static Logger LOGGER = LoggerFactory
            .getLogger(GuavaCache.class);

    private Cache<String, Object> cache;

    private Long maximumSize = 1000000L;  //可从配置文件读取

    private Integer concurrencyLevel = 8;  //可从配置文件读取


    private ConcurrentHashMap<String, Long>[] expireSegments;

    private static final Equivalence<Object> keyEquivalence = Equivalence.equals();

    private int segmentShift;

    private int segmentMask;

    public GuavaCache() {
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        cache = CacheBuilder.newBuilder()
                .maximumSize(maximumSize)
                .concurrencyLevel(concurrencyLevel)
                .recordStats()
                .build();
        int segmentShift = 0;
        int segmentCount = 1;
        while (segmentCount < concurrencyLevel) {
            ++segmentShift;
            segmentCount <<= 1;
        }
        this.segmentShift = 32 - segmentShift;
        segmentMask = segmentCount - 1;
        expireSegments = new ConcurrentHashMap[segmentCount];
        for(int i=0;i<segmentCount;i++) {
            expireSegments[i] = new ConcurrentHashMap<String, Long>();
            new Terminator(expireSegments[i]).start();
        }
        new Doctor().start();
    }

    /**
     * 缓存过期项清理
     */
    class Terminator extends Thread {

        private ConcurrentHashMap<String, Long> expireMap;

        public Terminator(ConcurrentHashMap<String, Long> expireMap){
            this.expireMap = expireMap;
        }

        @Override
        public void run() {
            while(true) {
                try {
                    Set<Map.Entry<String, Long>> entrySet = expireMap.entrySet();
                    Iterator<Map.Entry<String, Long>> it = entrySet.iterator();
                    while(it.hasNext()) {
                        Map.Entry<String, Long> entry = it.next();
                        if(entry.getValue() <= System.currentTimeMillis()) {
                            cache.invalidate(entry.getKey());
                            expireMap.remove(entry.getKey());
                            LOGGER.debug("key->" + entry.getKey() + "过期清理成功");
                        }
                    }
                    int clearInterval = 10;  //可从配置文件读取
                    Thread.sleep(clearInterval*1000);
                } catch (Exception e) {
                    LOGGER.error("LocalCacheUtil Terminator执行失败", e);
                }
            }
        }
    }

    /**
     * 本地缓存自检程序
     */
    class Doctor extends Thread {
        @Override
        public void run() {
            while(true) {
                try {
                    long cacheSize = cache.size();
                    CacheStats cacheStats = cache.stats();
                    String cacheInfo = "Local cache self check information,stats->" + cacheStats.toString() + ",cache size->" + cacheSize;
                    LOGGER.info(cacheInfo);
                    int sizeThreshold = 80;   //可从配置文件读取
                    if(((double)cacheSize/maximumSize)*100 >= sizeThreshold) {
                        cacheInfo = "本地缓存使用率过高,最大缓存量:"+maximumSize+",当前缓存量:"+cacheSize;
                        LOGGER.warn(cacheInfo);
                    }
                    int selfCheckInterval = 10;
                    Thread.sleep(selfCheckInterval*1000);
                } catch (Exception e) {
                    LOGGER.error("LocalCacheUtil Doctor execute error", e);
                }
            }
        }
    }

    /**
     * 缓存查询
     * @param key 要查询的缓存键
     * @return 查询到的缓存值
     */
    public <T> T get(String key) {
        T res = (T) cache.getIfPresent(key);
        return res;
    }

    /**
     * 向缓存中添加缓存项
     * @param key 要存储的缓存键
     * @param value 要存储的缓存值
     * @param seconds 缓存要存储的时间(<=0永不失效)
     * @return OK:设置成功 ERR:设置失败
     */
    public String set(final String key, Object value, Integer seconds) {
        return set(key, value, seconds, false);
    }

    /**
     * 向缓存中添加缓存项
     * @param key 要存储的缓存键
     * @param value 要存储的缓存值
     * @param seconds 缓存要存储的时间(<=0永不失效)
     * @param sync2OtherNode 将变化同步到其他实例节点,true:同步;false:不同步
     * @return OK:设置成功 ERR:设置失败
     */
    public String set(final String key, Object value, Integer seconds,Boolean sync2OtherNode) {
        return _set(key, value, seconds);
    }

    /**
     * 向缓存中添加缓存项
     * @param key 要存储的缓存键
     * @param value 要存储的缓存值
     * @param seconds 缓存要存储的时间(<=0永不失效)
     * @return OK:设置成功 ERR:设置失败
     */
    private String _set(final String key, Object value, Integer seconds) {
        try {
            if(seconds > 0) {
                int hash = hash(key);
                segmentFor(hash).put(key, System.currentTimeMillis() + seconds*1000);
            }
            cache.put(key, value);
            return "OK";
        } catch (Exception e) {
            LOGGER.error("put object into cache fired,key:{},value:{}",key,value);
            return "ERR";
        }
    }

    /**
     * 删除缓存
     * @param key 要删除的缓存键
     * @return 成功删除缓存记录数,如果缓存不存在返回值为0
     */
    public Long del(final String key) {
        return del(key,false);
    }

    /**
     * 删除缓存
     * @param key 要删除的缓存键
     * @param sync2OtherNode 将变化同步到其他实例节点,true:同步;false:不同步
     * @return 成功删除缓存记录数,如果缓存不存在返回值为0
     */
    public Long del(final String key,boolean sync2OtherNode) {
        return _del(key);
    }

    /**
     * 删除缓存
     * @param key 要删除的缓存键
     * @return 成功删除缓存记录数,如果缓存不存在返回值为0
     */
    private Long _del(final String key) {
        cache.invalidate(key);
        LOGGER.warn("delete object from cache,key:{}",key);
        return 1L;
    }

    private int hash(Object key) {
        int h = keyEquivalence.hash(key);
        return rehash(h);
    }

    private int rehash(int h) {
        h += (h << 15) ^ 0xffffcd7d;
        h ^= (h >>> 10);
        h += (h << 3);
        h ^= (h >>> 6);
        h += (h << 2) + (h << 14);
        return h ^ (h >>> 16);
    }

    private ConcurrentHashMap<String, Long> segmentFor(int hash) {
        return expireSegments[(hash >>> segmentShift) & segmentMask];
    }
}

Guava maven

<!-- 本地缓存框架包依赖 begin -->
        <dependency>
            <groupId>com.google.guava</groupId>
            <artifactId>guava</artifactId>
            <version>18.0</version>
        </dependency>
        <!-- 本地缓存框架包依赖 end -->

 

© 著作权归作者所有

共有 人打赏支持
山东和湖北
粉丝 0
博文 6
码字总数 4761
作品 0
昌平
程序员
Guava库学习:学习Guava Cache知识汇总

原文地址:Guava库学习:学习Guava Cache知识汇总 至此,我们结束了对Guava Cache 缓存机制的学习,在学习过程中,我们学习了如何简单的通过MapMaker创建最简单的ConcurrentMap缓存,我们也了...

Realfighter
2014/12/21
0
1
Guava库学习:学习Guava Cache(七)RemovalListener(2)

原文地址:Guava库学习:学习Guava Cache(七)RemovalListener(2)_RemovalListeners 接着上一篇Guava库学习:学习Guava Cache(七)RemovalListener(1)RemovalNotification,我们继续G...

Realfighter
2014/12/21
0
4
分布式缓存系列之guava cache

guava是google的一个开源java框架,其github地址是 https://github.com/google/guava。guava工程包含了若干被Google的 Java项目广泛依赖的核心库,例如:集合 [collections] 、缓存 [caching...

浮云骑士LIN
07/22
0
0
guava cache与spring集成

缓存的背景 缓存,在我们日常开发中是必不可少的一种解决性能问题的方法。简单的说,cache 就是为了提升系统性能而开辟的一块内存空间。在cpu进行计算的时候, 首先是读取寄存器,然后内存,...

爪哇小贩
2016/11/20
973
0
Guava 源码分析之Cache的实现原理

前言 Google 出的 Guava 是 Java 核心增强的库,应用非常广泛。 我平时用的也挺频繁,这次就借助日常使用的 Cache 组件来看看 Google 大牛们是如何设计的。 缓存 本次主要讨论缓存。缓存在日...

crossoverJie
01/20
0
0

没有更多内容

加载失败,请刷新页面

加载更多

HashMap工作原理及实现

HashMap工作原理及实现 1. 概述 什么时候会使用HashMap?他有什么特点? 知道HashMap的工作原理吗? 知道get和put的原理吗? 知道hash的实现吗?为什么要这样实现? 如果HashMap的大小超过了...

傅小水water
16分钟前
0
0
swagger如何屏蔽某些接口,不对外公开--使用@ApiIgnore

@ApiIgnore@RestController@RequestMapping(value = "/i18nTest")public class I18nTestController {// @Resource// private LocaleMessageSourceService localeMessageSourceSe......

karma123
19分钟前
0
0
大数据技术学习,大数据处理为何选择Spark,而不是Hadoop

大数据处理为何选择Spark,而不是Hadoop。 一.基础知识 1.Spark Spark是一个用来实现快速而通用的集群计算的平台。 在速度方面,Spark扩展了广泛使用的MapReduce计算模型,而且高效地支持更多...

董黎明
26分钟前
0
0
Java程序员的书籍清单

我自己一路来,看过的书籍,都是经典,我自己也在不断地回溯,在这里分享给大家(排名不分先后,这里仅仅是我自己购买这些书籍的时间顺序排列): 《高效程序员的45个习惯 敏捷开发修炼之道》...

ChinaHYF
53分钟前
1
0
DeepMind 开源图神经网络的代码

用于支持论文《Relational inductive biases, deep learning, and graph networks》。 github A graph network takes a graph as input and returns a graph as output. The input graph has......

shengjuntu
今天
2
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部