本文目录导读:

在Java中清理过期缓存有多种实现方式,这里提供几个常用的案例方案:
使用Guava Cache(推荐)
import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;
import java.util.concurrent.TimeUnit;
public class GuavaCacheExample {
// 创建缓存,设置过期策略
private static Cache<String, Object> cache = CacheBuilder.newBuilder()
// 写入后10分钟过期
.expireAfterWrite(10, TimeUnit.MINUTES)
// 访问后5分钟过期(如果没被访问则过期)
.expireAfterAccess(5, TimeUnit.MINUTES)
// 设置最大缓存数量
.maximumSize(1000)
.build();
public static void main(String[] args) {
// 存入缓存
cache.put("key1", "value1");
// 获取缓存(如果过期返回null)
Object value = cache.getIfPresent("key1");
// 移除缓存
cache.invalidate("key1");
// 清理所有过期缓存(Guava自动清理,也可手动调用)
cache.cleanUp();
}
}
使用Caffeine Cache(性能更好)
import com.github.benmanes.caffeine.cache.Cache;
import com.github.benmanes.caffeine.cache.Caffeine;
import java.util.concurrent.TimeUnit;
public class CaffeineCacheExample {
private static Cache<String, Object> cache = Caffeine.newBuilder()
// 写入后5分钟过期
.expireAfterWrite(5, TimeUnit.MINUTES)
// 访问后2分钟过期
.expireAfterAccess(2, TimeUnit.MINUTES)
// 最大缓存数
.maximumSize(5000)
// 缓存淘汰监听器
.removalListener((key, value, cause) -> {
System.out.println("缓存被移除: " + key + ", 原因: " + cause);
})
.build();
public static void main(String[] args) {
cache.put("user_001", userData);
// 获取缓存,如果过期返回null
Object data = cache.getIfPresent("user_001");
// 自动清理过期缓存(Caffeine会自动执行)
cache.cleanUp();
}
}
自定义延时清理方案
import java.util.concurrent.*;
public class CustomCacheCleaner {
private static ConcurrentHashMap<String, CacheEntry> cache = new ConcurrentHashMap<>();
private static ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);
static class CacheEntry {
Object value;
long expireTime;
CacheEntry(Object value, long expireTime) {
this.value = value;
this.expireTime = expireTime;
}
boolean isExpired() {
return System.currentTimeMillis() > expireTime;
}
}
// 启动定时清理任务
static {
scheduler.scheduleAtFixedRate(() -> {
cleanExpiredCache();
}, 0, 1, TimeUnit.MINUTES); // 每分钟执行一次
}
// 存入缓存(带过期时间)
public static void put(String key, Object value, long ttl, TimeUnit unit) {
long expireTime = System.currentTimeMillis() + unit.toMillis(ttl);
cache.put(key, new CacheEntry(value, expireTime));
}
// 获取缓存(自动检查过期)
public static Object get(String key) {
CacheEntry entry = cache.get(key);
if (entry == null || entry.isExpired()) {
cache.remove(key);
return null;
}
return entry.value;
}
// 清理过期缓存
public static void cleanExpiredCache() {
long now = System.currentTimeMillis();
cache.entrySet().removeIf(entry -> entry.getValue().isExpired());
}
}
使用Redis(分布式场景)
import org.springframework.data.redis.core.RedisTemplate;
import java.util.concurrent.TimeUnit;
public class RedisCacheExample {
private RedisTemplate<String, Object> redisTemplate;
// 存入缓存,设置过期时间
public void setWithExpire(String key, Object value, long timeout, TimeUnit unit) {
redisTemplate.opsForValue().set(key, value, timeout, unit);
}
// 获取缓存(Redis自动处理过期)
public Object get(String key) {
return redisTemplate.opsForValue().get(key);
}
// 手动清理过期键
public void cleanExpiredKeys() {
// Redis的key过期是由Redis自身管理的
// 这里可以批量删除某些模式的key
Set<String> keys = redisTemplate.keys("pattern:*");
if (keys != null && !keys.isEmpty()) {
redisTemplate.delete(keys);
}
}
}
使用Ehcache
import org.ehcache.Cache;
import org.ehcache.CacheManager;
import org.ehcache.config.builders.CacheConfigurationBuilder;
import org.ehcache.config.builders.CacheManagerBuilder;
import org.ehcache.config.builders.ExpiryPolicyBuilder;
import java.time.Duration;
public class EhcacheExample {
public static void main(String[] args) {
CacheManager cacheManager = CacheManagerBuilder.newCacheManagerBuilder().build();
cacheManager.init();
Cache<String, Object> cache = cacheManager.createCache("myCache",
CacheConfigurationBuilder.newCacheConfigurationBuilder(
String.class, Object.class,
// 设置过期时间
ExpiryPolicyBuilder.timeToLiveExpiration(Duration.ofMinutes(10))
));
cache.put("key", "value");
Object value = cache.get("key");
// Ehcache自动清理过期缓存
cacheManager.close();
}
}
最佳实践建议
- 选择合适工具:单机应用推荐Guava或Caffeine,分布式应用推荐Redis
- 设置合理过期时间:根据业务需求设置TTL
- 结合懒清理:访问时检查过期比定时清理更高效
- 监控缓存使用:定期检查缓存命中率,调整策略
// 懒清理示例(访问时检查)
public Object getFromCache(String key) {
CacheEntry entry = cache.get(key);
if (entry != null && entry.isExpired()) {
cache.remove(key); // 清理过期缓存
return null;
}
return entry != null ? entry.value : null;
}
选择哪种方案取决于你的具体场景:单机应用推荐Caffeine/Guava,分布式系统推荐Redis。