Guava cache 本地缓存

本文深入探讨了在项目开发中使用Guava构建本地缓存的优势,对比HashMap,Guava提供了更完善的并发处理、内存管理、刷新机制及容量限制策略。通过具体代码示例,展示了如何构建双层LoadingCache,实现高效的数据缓存与更新。

项目开发中很多程序员喜欢用HashMap来构建本地缓存,存在并发、内存泄漏、刷新机制不健全(某些场景下我们希望定时删除或刷新缓存)、容量限制(当超过设置的最大缓存量时使用LRU算法淘汰最久未使用的缓存数据)等问题,推荐使用Google的Guava来构建本地缓存。

  • 引包

<dependency>
    <groupId>com.google.guava</groupId>
    <artifactId>guava</artifactId>
    <version>20.0</version>
</dependency>  
  • 构建缓存

//实例:双层LoadingCache,全局缓存map中嵌套某数据类型的缓存map
private  final LoadingCache<String, LoadingCache<String,DataType>> cacheMap
            = CacheBuilder.newBuilder()
            .maximumSize(200) // 设置缓存的最大容量
            .build(new CacheLoader<String, LoadingCache<String,DataType>>() {
                @Override
                public LoadingCache<String,DataType> load(String key) throws Exception {
                    return CacheBuilder.newBuilder()
                    .maximumSize(2000) 
                    .expireAfterWrite(10, TimeUnit.MINUTES) //失效时间
                    .refreshAfterWrite(2, TimeUnit.MINUTES) //刷新时间
                    .build(new CacheLoader<String, DataType>() {
                        @Override
                        public DataType load(String key1) throws Exception {
                            return getDataType(key1);
                        }
                    });
                }
            });

使用CacheBuilder能构建出两种类型的cache:Cache与LoadingCache,上面的代码为LoadingCache。(使用Guava cache构建本地缓存

Cache是通过CacheBuilder的build()方法构建,它是Gauva提供的最基本的缓存接口,并且它提供了一些常用的缓存api:

Cache<Object, Object> cache = CacheBuilder.newBuilder().build();
// 放入/覆盖一个缓存
cache.put("k1", "v1");
// 获取一个缓存,如果该缓存不存在则返回一个null值
Object value = cache.getIfPresent("k1");
// 获取缓存,当缓存不存在时,则通Callable进行加载并返回。该操作是原子
Object getValue = cache.get("k1", new Callable<Object>() {
	@Override
	public Object call() throws Exception {
		return null;
	}
});

LoadingCache继承自Cache,在构建LoadingCache时,需要通过CacheBuilder的build(CacheLoader<? super K1, V1> loader)方法构建

 LoadingCache<Object, Object> loadingCache = CacheBuilder.newBuilder().build(new CacheLoader<Object, Object>() {
            @Override
            public Object load(Object key) throws Exception {
                return null;
            }
        });
// 获取缓存,当缓存不存在时,会通过CacheLoader自动加载,该方法会抛出ExecutionException异常
loadingCache.get("k1");
// 以不安全的方式获取缓存,当缓存不存在时,会通过CacheLoader自动加载,该方法不会抛出异常
loadingCache.getUnchecked("k1");

 

### Guava Cache 本地缓存的使用方法 Guava Cache 是 Google 提供的一个高性能本地缓存库,适用于需要高并发读写、缓存大小有限、允许数据短暂不一致的场景。其设计灵感来源于 `ConcurrentHashMap`,具备线程安全特性,并支持多种缓存清理策略,如基于大小、时间或引用强度等。 #### 创建缓存对象 Guava 使用 `CacheBuilder` 类来构建缓存实例,采用建造者模式进行配置。通过链式调用设置缓存的最大容量、过期时间、并发级别等参数: ```java import com.google.common.cache.Cache; import com.google.common.cache.CacheBuilder; public class GuavaCacheExample { private static final Cache<String, String> cache = CacheBuilder.newBuilder() .maximumSize(100) // 设置最大缓存条目数 .expireAfterWrite(10, TimeUnit.MINUTES) // 写入后10分钟过期 .build(); } ``` 该方式创建的缓存对象默认不会自动加载数据,若需在 key 不存在时自动计算值,可以结合 `CacheLoader` 实现: ```java import com.google.common.cache.CacheLoader; private static final Cache<String, String> cacheWithLoader = CacheBuilder.newBuilder() .maximumSize(50) .build(new CacheLoader<String, String>() { @Override public String load(String key) { return "default-" + key; // 当key不存在时返回默认值 } }); ``` #### 缓存的基本操作 Guava Cache 支持常见的缓存操作,包括插入、获取、删除等: - **插入数据**:使用 `put(key, value)` 方法手动插入键值对。 - **获取数据**:使用 `getIfPresent(key)` 获取已存在的值,或 `get(key)` 结合 `CacheLoader` 自动加载。 - **删除数据**:调用 `invalidate(key)` 删除指定键的缓存项;`invalidateAll()` 清除全部缓存。 - **统计信息**:通过 `cache.stats()` 获取缓存命中率、加载次数等统计信息。 示例代码如下: ```java // 插入缓存 cache.put("user:1001", "Alice"); // 获取缓存(存在则返回,否则为 null) String user = cache.getIfPresent("user:1001"); // 获取缓存并自动加载(当 key 不存在时触发 CacheLoader) String loadedUser = cacheWithLoader.getUnchecked("user:1002"); // 删除缓存 cache.invalidate("user:1001"); ``` #### 缓存失效策略 Guava Cache 支持以下几种缓存失效机制: - **基于大小**:通过 `maximumSize(long size)` 设置最大缓存条目数,超过后根据最近最少使用(LRU)策略清除旧条目。 - **基于时间**:通过 `expireAfterWrite(long duration, TimeUnit unit)` 或 `expireAfterAccess(long duration, TimeUnit unit)` 设置写入或访问后的存活时间。 - **基于引用强度**:通过 `weakKeys()` 或 `softValues()` 配置键值的垃圾回收策略,适合内存敏感型应用[^3]。 #### 异步刷新与监听器 Guava Cache 还支持异步刷新机制和缓存事件监听: - **刷新机制**:使用 `refresh(key)` 方法可异步重新加载缓存值,适用于缓存仍可用但需更新的场景。 - **监听器**:通过 `removalListener(RemovalListener<? super K, ? super V> listener)` 添加缓存移除监听器,用于记录日志、统计或清理资源。 ```java import com.google.common.cache.RemovalListener; import com.google.common.cache.RemovalNotification; RemovalListener<String, String> removalListener = new RemovalListener<>() { public void onRemoval(RemovalNotification<String, String> notification) { System.out.println("Removed key: " + notification.getKey() + ", value: " + notification.getValue()); } }; private static final Cache<String, String> cacheWithListener = CacheBuilder.newBuilder() .maximumSize(100) .removalListener(removalListener) .build(); ``` --- ###
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值