美文网首页
Guava缓存简介+demo+克隆类的使用

Guava缓存简介+demo+克隆类的使用

作者: salt丶 | 来源:发表于2020-07-03 17:12 被阅读0次

    Guava Cache简介

    Guava是谷歌提供的一个核心Java类库,其中包括新的集合类型、不可变集合、图库,以及用于并发、I/O、Hash、缓存、字符串等的 实用工具。它在谷歌中的大多数Java项目中被广泛使用,也被许多其他公司广泛使用,熟练掌握这些工具类能帮助我们快速的处理日常开发中的一些问题,比如,不可变集合、集合的转换、字符串处理、本地缓存等

    日常开发中的使用场景

    在我们日常的开发中,当多次获取同一份数据而数据变化不频繁时,我们可以考虑使用缓存。

    这里用到的就是内存和硬盘的性能不对等,我们知道内存的读取速度很快,而硬盘相对来说比较慢

    而传统的关系型数据库把数据存储在硬盘上,这样在高并发读写的场景下,就会出现性能瓶颈

    这个时候,如果在数据库前面加一层缓存,把数据库里面的热点数据缓存一份到内存中,读取的时候直接从内存中取,这样就可以大大的提升读取的性能

    Guava中的缓存实现

    Guava中的缓存是本地缓存的实现,与ConcurrentMap相似,但不完全一样。最基本的区别就是,ConcurrentMap会一直保存添加进去的元素,除非你主动remove掉。而Guava Cache为了限制内存的使用,通常都会设置自动回收

    Guava Cache的使用场景

    以空间换取时间,就是你愿意用内存的消耗来换取读取性能的提升 你已经预测到某些数据会被频繁的查询 缓存中存放的数据不会超过内存空间

    Guava Cache详细介绍:原文链接:https://blog.csdn.net/pzjtian/article/details/106910046

    如何使用Guava Cache:

    先来看一个简单示例,缓存字符串实例的大小形式。首先,我们创建ChcheLoader,用于计算存储在缓存中的值,然后我们便捷的CacheBuilder类依照规范构建缓存:

    @Test
    public void whenCacheMiss_thenValueIsComputed() {
        CacheLoader<String, String> loader;
        loader = new CacheLoader<String, String>() {
            @Override
            public String load(String key) {
                return key.toUpperCase();
            }
        };
    
        LoadingCache<String, String> cache;
        cache = CacheBuilder.newBuilder().build(loader);
    
        assertEquals(0, cache.size());
        assertEquals("HELLO", cache.getUnchecked("hello"));
        assertEquals(1, cache.size());
    }
    

    因为“hello” 键对应值在缓存中没有,所以值被计算并缓存。注意,我们使用getUnchecked() 方法,如果对应值不存在,则计算并缓存值到缓存中

    Guava Cache参数配置说明:

    //缓存接口这里是LoadingCache,LoadingCache在缓存项不存在时可以自动加载缓存
            LoadingCache<Integer,Student> studentCache
                    //CacheBuilder的构造函数是私有的,只能通过其静态方法newBuilder()来获得CacheBuilder的实例
                    = CacheBuilder.newBuilder()
                    //设置并发级别为8,并发级别是指可以同时写缓存的线程数
                    .concurrencyLevel(8)
                    //设置写缓存后8秒钟过期
                    .expireAfterWrite(8, TimeUnit.SECONDS)
                    //设置缓存容器的初始容量为10
                    .initialCapacity(10)
                    //设置缓存最大容量为100,超过100之后就会按照LRU最近虽少使用算法来移除缓存项
                    .maximumSize(100)
                    //设置要统计缓存的命中率
                    .recordStats()
                    //设置缓存的移除通知
                    .removalListener(new RemovalListener<Object, Object>() {
                        @Override
                        public void onRemoval(RemovalNotification<Object, Object> notification) {
                            System.out.println(notification.getKey() + " was removed, cause is " + notification.getCause());
                        }
                    })
                    //build方法中可以指定CacheLoader,在缓存不存在时通过CacheLoader的实现自动加载缓存
                    .build(
                            new CacheLoader<Integer, Student>() {
                                @Override
                                public Student load(Integer key) throws Exception {
                                    System.out.println("load student " + key);
                                    Student student = new Student();
                                    student.setId(key);
                                    student.setName("name " + key);
                                    return student;
                                }
                            }
                    );
    

    具体使用Guava缓存 java代码:

    导入依赖:
                    <dependency>
                <groupId>com.google.guava</groupId>
                <artifactId>guava</artifactId>
                <version>20.0</version>
            </dependency>
    
    public class GuavaService {
    
        @Autowired
        private UserMapper userMapper;
    
        public LoadingCache<String, List<User>> userListCache = CacheBuilder.newBuilder()
                .expireAfterWrite(5, TimeUnit.SECONDS)
                .maximumSize(2)
                .build(
                        new CacheLoader<String, List<User>>() {
                            @Override
                            public List<User> load(String key) throws Exception {
                                return userMapper.queryUserList();
                            }
                        }
                );
    
        public List<User> getUserList(){
            return userListCache.getUnchecked("ALL");
        }
    
    }
    
    @RestController
    public class GuavaTestController {
    
        @Autowired
        GuavaService guavaService;
    
        @RequestMapping("/test1")
        public List<User> test1(){
            return guavaService.getUserList();
        }
    }
    

    踩坑记录:在取缓存赋值给List时,直接对原List操作,导致其他地方取这个缓存的时候值发生了变化。

    @RequestMapping("/test2")
        public List<User> test2(){
            List<User> list = guavaService.getUserList();
            User user = new User();
            user.setName("testguava");
            user.setId(5555);
            user.setMale("男");
            list.add(user);
            return list;
        }
    
    

    当调用test2的时候,userListCache这个缓存值会不断增加,当缓存过期后,恢复正常。

    image-20200703163215480.png
    image-20200703163259110.png

    正确操作应该是把缓存取出的值重新赋值给List,对新List进行操作,也就是克隆值。

    @RequestMapping("/test2")
        public List<User> test2(){
            List<User> userList = new ArrayList<User>();
            List<User> list = guavaService.getUserList();
            for (User user:list) {
                userList.add(user);
            }
            User user = new User();
            user.setName("testguava");
            user.setId(5555);
            user.setMale("男");
            userList.add(user);
            return userList;
        }
    

    这里推荐另一种方式进行该操作,使用httpclient包下的 CloneUtils.cloneObject方法进行数据的克隆。

    1、导入依赖:
            <dependency>
          <groupId>org.apache.httpcomponents</groupId>
          <artifactId>httpclient</artifactId>
          <version>4.3.6</version>
        </dependency>
      
    2、
    import org.apache.http.client.utils.CloneUtils;
    
    3、
    List<User> targets = CloneUtils.cloneObject(GuavaService.getUserList());
    //然后对targets直接操作就行
    

    相关文章

      网友评论

          本文标题:Guava缓存简介+demo+克隆类的使用

          本文链接:https://www.haomeiwen.com/subject/skzsqktx.html