Guava Cache
Guava Cache
山东和湖北 发表于2年前
Guava Cache
  • 发表于 2年前
  • 阅读 64
  • 收藏 0
  • 点赞 2
  • 评论 0

标题:腾讯云 新注册用户域名抢购1元起>>>   

摘要: 不废话,贴代码
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 -->

 

标签: Guava Cache
共有 人打赏支持
粉丝 0
博文 5
码字总数 4761
×
山东和湖北
如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!
* 金额(元)
¥1 ¥5 ¥10 ¥20 其他金额
打赏人
留言
* 支付类型
微信扫码支付
打赏金额:
已支付成功
打赏金额: