zoukankan      html  css  js  c++  java
  • Guava Cache 使用笔记

     https://www.cnblogs.com/parryyang/p/5777019.html

    https://www.cnblogs.com/shoren/p/guava_cache.html

    Java 高并发缓存与Guava Cache

     Guava Cache与ConcurrentMap很相似,Guava Cache能设置回收,能解决在大数据内存溢出的问题,源代码如下:

    http://blog.csdn.net/congcong68/article/details/41146295

    http://www.jianshu.com/p/afe7b2dccee0

    Guava Cache的使用

    96 
    JohnShen 
    2016.01.07 16:58* 字数 1177 阅读 3593评论 4

    本文部分内容翻译自官方文档,部分内容和示例根据自己的理解完成
    原文地址:https://github.com/google/guava/wiki/CachesExplained

    Guava Cache的适用场景

    Cache(缓存)在很广泛的场景下都是很有用的。比如,当一个值的计算或者检索的代价很大,并且在稍后的特定输入发生后,你将不止一次的需要这个值的时候,就应当考虑使用Cache了。

    Cache是和ConcurrentMap很相像的东西。最本质的不同就是,ConcurrentMap持有所有被添加进的元素,直到它们专门被移除。从另一方面来说,为了使得内存的使用可控,Cache通常来说是可配置来自动回收元素的。在一些情况下,即使LoadingCache也会很有用,虽然由于他的自动缓存加载机制,它不回收元素。

    通常,Guava Cache组件在下面的场景中适用:

    • 你想花费一些内存来提高速度。
    • 你预期到一些key的值将被不止一次地被查询。
    • 你的缓存将不会需要比内存能够存储的数据更多。(Guava Cache对于一个单独运行的应用来说是本地的。它们不回将数据存储在文件中或者外部服务器上。如果这不适合你的需求,那么考虑使用其它的工具,比如Memcached

    如果上面的这些都符合你的需要,那么Guava Cache组件将适合你!
    获得一个Cache是使用CacheBuilder来完成的。

    注意:如果你不需要Cache的一些特性,那么ConcurrentHashMap是更加有内存效率的--但是使用任何旧的ConcurrentMap都会很难或者几乎不可能去完成Cache所支持的一些特性。

    Guava Cache的使用示例

    使用缓存时,最常遇到的场景需要就是:

    "获取缓存-如果没有-则计算"[get-if-absent-compute]的原子语义.

    具体含义:

    1. 从缓存中取。
    2. 缓存中存在该数据,直接返回;
    3. 缓存中不存在该数据,从数据源中取。
    4. 数据源中存在该数据,放入缓存,并返回;
    5. 数据源中不存在该数据,返回空。

    下面这段代码实现了一个做在DAO层的本地缓存。其中,getPOIList()是对外提供的方法,该方法中实现了上述逻辑。getPOIListFromDB()是用于模拟从数据库中取数据的方法。

    import com.google.common.base.Optional;
    import com.google.common.cache.Cache;
    import com.google.common.cache.CacheBuilder;
    import com.google.common.collect.ImmutableList;
    
    import java.util.Collections;
    import java.util.List;
    import java.util.concurrent.Callable;
    import java.util.concurrent.ExecutionException;
    
    public class Dao {
        Cache<String, List<String>> poiCache = CacheBuilder.newBuilder().build();
    
        @SuppressWarnings("unchecked")
        public List<String> getPOIList(final String cityId) {
            List returnList = null;
            try {
                returnList = poiCache.get(cityId, new Callable<List<String>>() {
                    @Override
                    public List<String> call(){
                        return getPOIListFromDB(cityId);
                    }
                });
            } catch (ExecutionException e) {
                // 记日志
            }
            return Optional.fromNullable(returnList).or(Collections.EMPTY_LIST);
        }
    
        @SuppressWarnings("unchecked")
        private List<String> getPOIListFromDB(String cityId){
            System.out.println("getting from DB, please wait...");
            List<String> returnList = null;
            // 模仿从数据库中取数据
            try {
                Thread.sleep(1000);
                switch (cityId){
                    case "0101" : 
                            returnList = ImmutableList.of("望京", "望京西", "望京南", "望京北"); break;
                    case "0102" : 
                            returnList = ImmutableList.of("a", "b", "c", "d"); break;
                }
            } catch (Exception e) {
                // 记日志
            }
            return Optional.fromNullable(returnList).or(Collections.EMPTY_LIST);
        }
    }

    用于测试的主方法:

    import java.util.Arrays;
    
    public class CacheTest {
        public static void main(String[] args) {
            Dao dao = new Dao();
    
            for (int i = 0; i < 3; i++) {
                System.out.println("--- " + i + " ---");
                System.out.println(Arrays.toString(dao.getPOIList("0101").toArray()));
                System.out.println(Arrays.toString(dao.getPOIList("0102").toArray()));
                System.out.println(Arrays.toString(dao.getPOIList("0103").toArray()));
                System.out.println();
            }
        }
    }

    控制台输出:

    --- 0 ---
    getting from DB, please wait...
    [望京, 望京西, 望京南, 望京北]
    getting from DB, please wait...
    [a, b, c, d]
    getting from DB, please wait...
    []
    
    --- 1 ---
    [望京, 望京西, 望京南, 望京北]
    [a, b, c, d]
    []
    
    --- 2 ---
    [望京, 望京西, 望京南, 望京北]
    [a, b, c, d]
    []

    运行后的输出结果表明了,只有第一次是从DB中取的数据,之后的两次都是从cache中取得的。

    为什么要把Cache对象放在DAO层?

    思考一下Cache的用途,能够想到在一个Application中,对同一种对象的缓存只需要一个就够了。比如示例中的poiCache是缓存city对应的poi信息的,那么在这个Application中最好只存在一个poiCache。
    实现这样的要求有以下几种方式:

      1. Spring的Singleton模式(推荐)
        比较常见的做法是将Server和DAO都作为单例的bean交给Spring容器管理,而将缓存放在DAO层不但实现了单例,也更合理(数据的缓存策略本身就应是数据访问层的一部分)。
      2. 静态初始化(不推荐)

    我刚开始使用时还以为Guava Cache跟HashMap一样,get(null)返回null。 

    http://blog.csdn.net/albertfly/article/details/51971086

  • 相关阅读:
    Tomcat的startup.bat启动后显示乱码--windows终端
    Java 文件组织形式
    连接Linux之win10子系统Linux安装与使用(一)
    连接Linux之win10子系统Linux安装与使用(二)
    vscode omnisharp server load timed out
    在唯一密钥属性“fileExtension”设置为“.json”时,无法添加类型为“mimeMap”的重复集合项
    vscode编译发布exe
    MySQL数据库一般设计规则
    .Net开发常用工具插件
    linx下对文件权限设置
  • 原文地址:https://www.cnblogs.com/ydxblog/p/7889496.html
Copyright © 2011-2022 走看看