guava Cache入门Demo

一、先引入依赖

		<!--guava缓存-->
        <dependency>
            <groupId>com.google.guava</groupId>
            <artifactId>guava</artifactId>
            <version>32.1.3-jre</version>
        </dependency>

二、测试demo

public class GuavaCacheDemo {
   //模拟Guava缓存
   private static class DataSource {
       // 模拟数据获取方法
       public String getValue(String key) {
           //模拟从数据库或其他数据源获取数据
           System.out.println("[数据源]正在查询key: " + key);
           try {
               TimeUnit.MILLISECONDS.sleep(200); // 模拟延迟
           } catch (InterruptedException e) {
               e.printStackTrace();
           }
           // 返回模拟数据
           return "value_" + key;
       }
   }
    public static void main(String[] args) throws ExecutionException, InterruptedException {
        DataSource dataSource = new DataSource();
        //1.构建缓存实例(核心配置)
        LoadingCache<String, String> cache = CacheBuilder.newBuilder()
                .maximumSize(100) // 最大容量
                .expireAfterWrite(5, TimeUnit.SECONDS) // 写入后5秒过期
                .refreshAfterWrite(3, TimeUnit.SECONDS) // 写入后3秒刷新
                .recordStats() // 开启统计
                // 3.配置缓存移除监听器
                .removalListener(notification -> {
                    System.out.println("[缓存移除] key: " + notification.getKey() + ", 原因 : " + notification.getCause());
                    //2.配置缓存加载逻辑
                }).build(new CacheLoader<String, String>() {
                    @Override
                    public String load(String key) throws Exception {
                        return dataSource.getValue(key);
                    }
                });
        //3.使用缓存
        System.out.println("===============第一次查询(缓存未命中)===============");
        System.out.println("结果:" + cache.get("key1"));

        System.out.println("===============第二次查询(缓存命中)===============");
        System.out.println("结果:" + cache.get("key1"));
        //手动输入缓存
        cache.put("key2", "shoudong key2");
        System.out.println("===============查询手动放入的缓存===============");
        System.out.println("结果:" + cache.get("key2"));

        //等待6秒,超过过期时间
        System.out.println("===============等待6秒,超过过期时间===============");
        TimeUnit.SECONDS.sleep(6);
        System.out.println("===============第三次查询(缓存过期,重新加载)===============");
        System.out.println("结果:" + cache.get("key1"));

        //打印缓存统计信息
        System.out.println("===============缓存统计信息===============");
        CacheStats stats = cache.stats();
        System.out.println("命中率: " + stats.hitRate());
        System.out.println("命中次数: " + stats.hitCount());
        System.out.println("未命中次数: " + stats.missCount());
        System.out.println("淘汰次数:" + stats.evictionCount());

        //手动清除某个缓存
        cache.invalidate("key2");
        System.out.println("===============手动清除key2缓存后再次查询===============");
        System.out.println("结果:" + cache.get("key2"));

        //关闭缓存(可选)
        cache.cleanUp();
    }
}

三、测试结果:

===============第一次查询(缓存未命中)===============
[数据源]正在查询key: key1
结果:value_key1
===============第二次查询(缓存命中)===============
结果:value_key1
===============查询手动放入的缓存===============
结果:shoudong key2
===============等待6秒,超过过期时间===============
===============第三次查询(缓存过期,重新加载)===============
[缓存移除] key: key1, 原因 : EXPIRED
[缓存移除] key: key2, 原因 : EXPIRED
[数据源]正在查询key: key1
结果:value_key1
===============缓存统计信息===============
命中率: 0.5
命中次数: 2
未命中次数: 2
淘汰次数:2
===============手动清除key2缓存后再次查询===============
[数据源]正在查询key: key2
结果:value_key2

四、适用场景

  1. 热点数据本地缓存:如电商商品详情、配置信息、用户基础信息(查询频繁、修改少);

  2. 减轻数据源压力:对数据库/RPC接口的查询结果缓存,减少下游服务调用量;

  3. 短期有效数据:如临时生成的令牌、会话信息(需设置过期时间);

  4. 单机场景:不依赖分布式缓存(如 Redis),追求低延迟(本地内存查询)。

五、关键注意点

  • 不支持分布式:仅存于当前应用进程,多实例部署会有数据一致性问题;

  • 内存限制:需配置 maximumSize 避免内存溢出,依赖 JVM 垃圾回收;

  • 过期策略:expireAfterWrite(写入后过期)、expireAfterAccess(访问后过期)按需选择。

### Guava 缓存的使用与实现 #### 创建和配置缓存实例 `LocalCache` 是整个 Guava Cache 的核心类,包含了数据结构以及基本操作方法[^1]。通过 `CacheBuilder` 类可以方便地构建并定制化缓存对象。 ```java import com.google.common.cache.Cache; import com.google.common.cache.CacheBuilder; // 构建一个简单的本地缓存实例 Cache<String, String> cache = CacheBuilder.newBuilder() .maximumSize(100) // 设置最大条目数为100 .build(); ``` #### 自定义加载器 对于更复杂的场景,可以通过指定 `CacheLoader` 来自动填充缺失键对应的值: ```java import com.google.common.base.Optional; import com.google.common.cache.CacheLoader; Cache<String, Optional<String>> loadingCache = CacheBuilder.newBuilder() .maximumSize(100) .build(new CacheLoader<String, Optional<String>>() { @Override public Optional<String> load(String key) throws Exception { return Optional.ofNullable(fetchValueForKey(key)); } }); ``` 这里展示了如何设置当请求不存在于缓存中的时候,默认调用给定的方法来获取该值,并将其加入到缓存中以便后续访问[^2]。 #### 添加、检索及移除元素 可以直接利用 put 方法向缓存添加新项;getIfPresent 可用于查询特定键是否存在及其关联值;而 invalidate 则允许删除单个或全部记录。 ```java // 向缓存中添加一项 cache.put("key", "value"); // 获取已存在的项 String value = cache.getIfPresent("key"); // 移除某项 cache.invalidate("key"); ``` #### 高级特性支持 Guava 还提供了诸如过期时间(expireAfterWrite/expireAfterAccess)、刷新机制(refresh)等功能的支持,这些都极大地方便了开发者针对不同应用场景灵活调整缓存行为。 #### 并发控制优化 由于设计之初就考虑到了多线程环境下的高效运作,因此即使是在高并发读写的条件下也能保持良好的性能表现。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值