文档章节

Guava Cache

山东和湖北
 山东和湖北
发布于 2016/05/11 18:01
字数 889
阅读 76
收藏 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 -->

 

© 著作权归作者所有

共有 人打赏支持
上一篇: Jgroups
下一篇: AOP
山东和湖北
粉丝 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

没有更多内容

加载失败,请刷新页面

加载更多

Framework7开发H5App如何禁止回退离开首页

将代码放到需要禁止回退的页面即可 主要代码 $(function () {  //防止页面后退  history.pushState(null, null, document.URL);     window.addEventListener('popstate', funct...

老查
2分钟前
0
0
Navicat使用教程(三):使用MySQL日志(第3部分)——慢速日志

下载Navicat for MySQL最新版本 Navicat for MySQL 是一套管理和开发 MySQL 或 MariaDB 的理想解决方案。使用Navicat for MySQL可以同时连接到 MySQL 和 MariaDB。Navicat for MySQL提供了强...

电池盒
7分钟前
0
0
威武 | 有我在,HTTPS更安全!亚洲诚信参展FIT 2019

12月12日-12月13日,备受瞩目的FIT 2019在上海宝华万豪酒店隆重举行。作为FreeBuf互联网安全创新大会(FIT)的长期战略合作伙伴,亚洲诚信受邀参加本次盛会,并与来自全球的行业先锋们聚焦前...

亚洲诚信
10分钟前
0
0
提高 JavaScript 开发效率的高级 VSCode 扩展!

摘要: VScode越来越火了啊。 原文:提高 JavaScript 开发效率的高级 VSCode 扩展! 作者:前端小智 Fundebug经授权转载,版权归原作者所有。 Quokka.js Quokka.js 是一个用于 JavaScript 和...

Fundebug
11分钟前
0
0
docker development note

// on developer clientsudo route -n add -net 172.17.0.0/16 192.168.99.100// on test docker serversudo iptables -A FORWARD -j ACCEPT...

kut
11分钟前
0
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部