文档章节

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 cache

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

浮云骑士LIN
07/22
0
0
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与spring集成

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

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

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

crossoverJie
01/20
0
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

Ubuntu18.04 显卡GF-940MX安装NVIDIA-390.77

解决办法: 下面就给大家一个正确的姿势在Ubuntu上安装Nvidia驱动: (a)首先去N卡官网下载自己显卡对应的驱动:www.geforce.cn/drivers (b)下载后好放在英文路径的目录下,怎么简单怎么来...

AI_SKI
今天
0
0
深夜胡思乱想

魔兽世界 最近魔兽世界出了新版本, 周末两天升到了满级,比之前的版本体验好很多,做任务不用抢怪了,不用组队打怪也是共享拾取的。技能简化了很多,哪个亮按哪个。 运维 服务器 产品 之间的...

Firxiao
今天
0
0
MySQL 8 在 Windows 下安装及使用

MySQL 8 带来了全新的体验,比如支持 NoSQL、JSON 等,拥有比 MySQL 5.7 两倍以上的性能提升。本文讲解如何在 Windows 下安装 MySQL 8,以及基本的 MySQL 用法。 下载 下载地址 https://dev....

waylau
今天
0
0
微信第三方平台 access_token is invalid or not latest

微信第三方开发平台code换session_key说的特别容易,但是我一使用就带来无穷无尽的烦恼,搞了一整天也无济于事. 现在记录一下解决问题的过程,方便后来人参考. 我遇到的这个问题搜索了整个网络也...

自由的开源
今天
2
0
openJDK之sun.misc.Unsafe类CAS底层实现

注:这篇文章参考了https://www.cnblogs.com/snowater/p/8303698.html 1.sun.misc.Unsafe中CAS方法 在sun.misc.Unsafe中CAS方法如下: compareAndSwapObject(java.lang.Object arg0, long a......

汉斯-冯-拉特
今天
3
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部