一、Guava是什么
Guava是一种基于开源的Java库,Google Guava源于2007年的"Google Collections Library"。这个库是为了方便编码,并减少编码错误。这个库用于提供集合,缓存,支持原语句,并发性,常见注解,字符串处理,I/O和验证的实用方法。
二、Guava Cache是什么
Guava cache是谷歌的Guva提供的cache模块,目前被常用在单机上的本地缓存,如果是分布式,它就无能为力。(本地缓存详见:https://my.oschina.net/u/2270476/blog/1805749)
Guava Cache与ConcurrentMap很相似,但也不完全一样。最基本的区别是ConcurrentMap会一直保存所有添加的元素,直到显式地移除。相对地,Guava Cache为了限制内存占用,通常都设定为自动回收元素。在某些场景下,尽管LoadingCache 不回收元素,它也是很有用的,因为它会自动加载缓存。
Guava Cache是在内存中缓存数据,相比较于数据库或redis存储,访问内存中的数据会更加高效。Guava官网介绍,下面的这几种情况可以考虑使用Guava Cache:
-
愿意消耗一些内存空间来提升速度。
-
预料到某些键会被多次查询。
-
缓存中存放的数据总量不会超出内存容量。
所以,可以将程序频繁用到的少量数据存储到Guava Cache中,以改善程序性能。具体的详细用法详见:https://www.cnblogs.com/fnlingnzb-learner/p/11022152.html
三、本次项目使用Guava Cache方法代码片段:
1、服务启动时加载缓存
package cn.uce.rms.common.cache;
import java.util.List;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import javax.annotation.Resource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.stereotype.Component;
import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;
import cn.uce.rms.comm.entity.RmsGroupTransportEntity;
import cn.uce.rms.monitor.biz.IRmsGroupBiz;
/**
* 本地缓存
* @Description guava
* @date 2018年12月06日 16:49:00
*/
@Component("monitorLocalCache")
public class MonitorLocalCache implements InitializingBean {
/**
* 日志
*/
private static final Logger log = LoggerFactory.getLogger(MonitorLocalCache.class);
/**
* 缓存 2小时未被读/写访问则回收
*/
private Cache<String, List<RmsGroupTransportEntity>> transportCache;
/**
* 缓存有效时间
*/
private static final int CACHE_ACCESS_DURATION = 2;
/**
* 运输班次缓存Key
*/
private static final String TRANSPORT_GROUP_CACHE = "TRANSPORT_GROUP_CACHE";
@Resource
private IRmsGroupBiz rmsGroupBiz;
@Override
public void afterPropertiesSet() {
// 缓存有效时长2小时
transportCache = CacheBuilder.newBuilder().expireAfterWrite(CACHE_ACCESS_DURATION, TimeUnit.HOURS)
.removalListener(notification -> log.info("[transport Cache Data] == {} was removed, cause is {}",
notification.getKey(), notification.getCause())).recordStats().build();
}
/**
* 将所有缓存的值置失效
* @Description
* @date 2018年12月23日 12:14:22
*/
public void invalidateAllLocalCache() {
// 运输班次
transportCache.invalidateAll();
}
/**
* 获取运输班次缓存数据
* @Description
* @return 运输班次结果集
* @throws ExecutionException 执行缓存异常
* @date 2018年12月06日 16:59:14
*/
public List<RmsGroupTransportEntity> transportGroupCache() throws ExecutionException {
// 获取RMS运输班次数据
return transportCache.get(TRANSPORT_GROUP_CACHE, () -> rmsGroupBiz.findTransportGroupFromProduct());
}
}
2、需要用到缓存时调用
/**
*
* @Description
* @date 2019年01月22日 11:57:00
*/
@Component("groupCacheSupport")
public class GroupCacheSupport {
/**
* 日志收集
*/
private static final Logger log = LoggerFactory.getLogger(GroupCacheSupport.class);
/**
* 本地缓存
*/
@Resource
private MonitorLocalCache monitorLocalCache;
public Map<String, List<RmsGroupTransportEntity>> findTransportMapGroupByGroupName() {
List<RmsGroupTransportEntity> resultList;
resultList = monitorLocalCache.transportGroupCache();
try {
resultList = monitorLocalCache.transportGroupCache();
// 过滤主班次
List<RmsGroupTransportEntity> newList = resultList.stream().filter(item -> item.getGroupType().equals(SUB.value())).collect(Collectors.toList());
// 按班次名称分组
Map<String, List<RmsGroupTransportEntity>> collect = newList.stream().collect(groupingBy(RmsGroupTransportEntity::getTransportGroupName));
for (String transportGroupName : collect.keySet()) {
// 以组列号作为Key生成Map,用于去重
Map<String, List<RmsGroupTransportEntity>> groupMap =
collect.get(transportGroupName).stream().collect(groupingBy(RmsGroupTransportEntity::getGroupOnlyoneCode));
// 获取当中的一个元素即可
List<RmsGroupTransportEntity> tmpList = new ArrayList<>(groupMap.get(groupMap.keySet().iterator().next()));
// 排序
tmpList.sort(comparing(RmsGroupTransportEntity::getSubSortNum));
// 覆盖原有的元素
resultMap.put(transportGroupName, tmpList);
}
} catch (ExecutionException e) {
log.error("获取运输班次时执行缓存失败", e);
}
return resultMap;
}
}