Java本地缓存详解
引言
在现代的Java应用开发中,本地缓存扮演着重要的角色。它通过将数据暂存于内存中,显著提高了数据访问的速度,减轻了数据库的压力,并增强了系统的响应能力。本文将详细介绍Java本地缓存的使用场景、使用方法,并提供一些流行的本地缓存框架的详解。
使用场景
1. 数据库查询结果缓存
数据库查询是应用中常见的性能瓶颈之一。通过将查询结果缓存在本地,可以避免重复的数据库访问,提高系统的响应速度。
2. 减少网络延迟
对于需要从远程服务获取数据的应用,本地缓存可以减少网络请求的次数,降低网络延迟的影响。
3. 计算密集型结果缓存
对于计算密集型的操作,如数学计算或复杂逻辑处理,将结果缓存可以避免重复计算,提高效率。
4. 会话缓存
在Web应用中,本地缓存可以用来存储用户会话信息,减少会话信息的数据库访问次数。
使用方法
1. 手写本地缓存
封装缓存实体类
首先,我们需要创建一个缓存实体类,用于存储缓存键、缓存值和过期时间。
@Data
public class CacheEntity {
private String key;
private Object value;
private Long expireTime;
}
创建缓存工具类
使用ConcurrentHashMap作为存储结构,并添加缓存管理功能,如添加、删除、查询和清除过期缓存。
public class CacheUtil {
private final static Map<String, CacheEntity> CACHE_MAP = new ConcurrentHashMap<>();
private static ScheduledExecutorService executorService = Executors.newSingleThreadScheduledExecutor();
static {
executorService.scheduleAtFixedRate(CacheUtil::clear, 1000L, 500L, TimeUnit.MILLISECONDS);
}
public static void put(String key, Object value, Long expire) {
CacheEntity cacheEntity = new CacheEntity();
cacheEntity.setKey(key);
cacheEntity.setValue(value);
if (expire > 0) {
Long expireTime = System.currentTimeMillis() + Duration.ofSeconds(expire).toMillis();
cacheEntity.setExpireTime(expireTime);
}
CACHE_MAP.put(key, cacheEntity);
}
public static Object get(String key) {
if (CACHE_MAP.containsKey(key)) {
CacheEntity cacheEntity = CACHE_MAP.get(key);
if (cacheEntity.getExpireTime() == null || cacheEntity.getExpireTime() > System.currentTimeMillis()) {
return cacheEntity.getValue();
}
CACHE_MAP.remove(key);
}
return null;
}
public static void remove(String key) {
CACHE_MAP.remove(key);
}
public static void clear() {
CACHE_MAP.entrySet().removeIf(entry -> entry.getValue().getExpireTime() != null && entry.getValue().getExpireTime() < System.currentTimeMillis());
}
}
2. Guava Cache
Guava Cache是Google提供的一套完善的JVM本地缓存框架,提供了缓存过期时间设置、缓存容量设置、多种淘汰策略、缓存监控等功能。
引入POM依赖
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>31.0.1-jre</version>
</dependency>
创建LoadingCache缓存
LoadingCache<Integer, String> cache = CacheBuilder.newBuilder()
.maximumSize(100)
.expireAfterWrite(10, TimeUnit.MINUTES)
.build(new CacheLoader<Integer, String>() {
@Override
public String load(Integer key) throws Exception {
return "Value for " + key;
}
});
3. Caffeine
Caffeine是一个高性能的Java本地缓存库,相比Guava Cache,它提供了更好的性能和更低的内存消耗。
引入POM依赖
<dependency>
<groupId>com.github.ben-manes.caffeine</groupId>
<artifactId>caffeine</artifactId>
<version>2.9.3</version>
</dependency>
开启缓存功能
Cache<Integer, String> cache = Caffeine.newBuilder()
.maximumSize(10000)
.expireAfterWrite(10, TimeUnit.MINUTES)
.build();
4. Ehcache
Ehcache是一个功能丰富的开源Java分布式缓存。它提供了丰富的缓存策略和易于使用的API。
引入POM依赖
<dependency>
<groupId>org.ehcache</groupId>
<artifactId>ehcache</artifactId>
<version>3.9.7</version>
</dependency>
配置缓存管理器
CacheManager cacheManager = CacheManagerBuilder.newCacheManagerBuilder().build();
CacheConfiguration<String, String> config = CacheConfigurationBuilder.newCacheConfigurationBuilder(
String.class, String.class, ResourcePoolsBuilder.heap(10))
.withExpiry(Expirations.timeToLiveExpiration(Duration.ofMinutes(10)))
.build();
Cache<String, String> cache = cacheManager.createCache("myCache", config);
总结
Java本地缓存是提高应用性能的重要手段。通过手写缓存或使用成熟的缓存框架如Guava Cache、Caffeine和Ehcache,我们可以有效地减少数据库访问次数,降低网络延迟,并提高系统的响应速度。选择合适的缓存策略和框架对于构建高性能Java应用至关重要。