本地缓存可以使用 EhCache 和 Google的 Guava来实现
分布式缓存可以使用 Memcached 和 redis 来实现
EhCache的本地实现
首先添加依赖
<dependency>
<groupId>org.ehcache</groupId>
<artifactId>ehcache</artifactId>
<version>3.8.1</version>
</dependency>
然后自定义一个EhCache的实现类
public class EhcacheExample {
public static void main(String[] args) {
CacheManager cacheManager = CacheManagerBuilder.newCacheManagerBuilder().build();
cacheManager.init();
Cache<String, String> myCeche = cacheManager.createCache("MYCECHE", CacheConfigurationBuilder.newCacheConfigurationBuilder(
String.class, String.class, ResourcePoolsBuilder.heap(10)));
Cache<String, String> myCeche2 = cacheManager.createCache("MYCECHE2", CacheConfigurationBuilder.newCacheConfigurationBuilder(
String.class, String.class, ResourcePoolsBuilder.heap(10)));
myCeche.put("testKey","value1");
myCeche2.put("testKey","value2");
String testKey = myCeche.get("testKey");
String testKey2 = myCeche2.get("testKey");
System.out.println("testKey = " + testKey);
System.out.println("testKey2 = " + testKey2);
//testKey = value1
//testKey2 = value2
cacheManager.close();
// CacheManager 下 可以有多个 Cache ,每个Cache 下可以有多个 k-v
}
}
使用guava 生成的缓存如下
public class GuavaCache {
public static void main(String[] args) throws ExecutionException {
LoadingCache<String, String> loadingCache = CacheBuilder.newBuilder()
//并发级别设置为5
.concurrencyLevel(5)
// 设置过期时间为8秒钟
.expireAfterAccess(8, TimeUnit.SECONDS)
// 初始化的容量长度为10
.initialCapacity(10)
// 最大的容量长度为100
.maximumSize(100)
//设置统计缓存的命中率
.recordStats()
//设置缓存的移除通知
.removalListener(new RemovalListener<Object, Object>() {
@Override
public void onRemoval(RemovalNotification<Object, Object> removalNotification) {
System.out.println(removalNotification.getKey() + " key was remove , cache is " + removalNotification.getValue());
}
})
//指定CacheLoader 缓存不存在时 ,可自动加载缓存
.build(new CacheLoader<String, String>() {
@Override
public String load(String key) throws Exception {
// 自动加载缓存业务
return "不存在的key : " + key;
}
});
String testGuava = "testGuava";
loadingCache.put(testGuava,"value1");
String resultValue = loadingCache.get(testGuava);
System.out.println("resultValue = " + resultValue);
resultValue = loadingCache.get(testGuava+"1");
System.out.println("resultValue2 = " + resultValue);
//第二种方式
Cache<String, String> objectCache = CacheBuilder.newBuilder().maximumSize(100).build();
objectCache.put(testGuava,"max100");
// 取一个存在的值
String result = objectCache.get(testGuava, new Callable<String>() {
@Override
public String call() throws Exception {
//自定义返回值
return "null";
// 执行的效果如下
// resultValue = value1
//resultValue2 = 不存在的key : testGuava1
//result = max100
//result = 不存在~~~~
如何手动实现一个本地缓存
附上代码
- 自定义一个缓存中存放的对象
@Data
@AllArgsConstructor
@NoArgsConstructor
public class MyCustomizeCache implements Comparable<MyCustomizeCache>{
/**
* key
*/
private Object key;
/**
* Value
*/
private Object value;
/**
* 上次访问时间
*/
private long lastTime;
/**
* 创建时间
*/
private long writeTime;
/**
*存活时间
*/
private long expireTime;
/**
* 命中次数
*/
private Integer hitCount;
@Override
public int compareTo(MyCustomizeCache myCustomizeCache) {
return hitCount.compareTo(myCustomizeCache.hitCount);
}
}
- 自定义一个全局的ConcurrentHashMap对象
public class MyCustomizeCacheClobal {
public static ConcurrentHashMap<String,MyCustomizeCache> concurrentHashMap=new ConcurrentHashMap<>();
}
- 定义一个自动检查的定时删除任务
public class ExpireThread implements Runnable{
@Override
public void run() {
while (true){
try {
TimeUnit.SECONDS.sleep(10);
expireCache();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
private void expireCache() {
System.out.println("检测存储是否过期");
for (String key : MyCustomizeCacheClobal.concurrentHashMap.keySet()) {
MyCustomizeCache customizeCache = MyCustomizeCacheClobal.concurrentHashMap.get(key);
long expireTime = TimeUnit.NANOSECONDS.toSeconds(System.nanoTime() - customizeCache.getWriteTime());
if (customizeCache.getExpireTime()>expireTime) {
continue;
}
//清除过期缓存
MyCustomizeCacheClobal.concurrentHashMap.remove(key);
}
}
}
- 实现一个存放缓存和获取缓存的工具类
public class MyCacheUtil {
/**
* 存放key、value
* @param key
* @param value
* @param expireTime
*/
public static void put(String key, Object value, long expireTime) {
if (StrUtil.isEmpty(key)) {
return;
}
// 判断在缓存中是否存在key
if (concurrentHashMap.containsKey(key)) {
MyCustomizeCache customizeCache = concurrentHashMap.get(key);
customizeCache.setValue(value);
customizeCache.setLastTime(System.currentTimeMillis());
customizeCache.setWriteTime(System.currentTimeMillis());
customizeCache.setExpireTime(expireTime);
customizeCache.setHitCount(customizeCache.getHitCount() + 1);
return;
}
MyCustomizeCache customizeCache = new MyCustomizeCache();
customizeCache.setKey(key);
customizeCache.setValue(value);
customizeCache.setLastTime(System.currentTimeMillis());
customizeCache.setWriteTime(System.currentTimeMillis());
customizeCache.setExpireTime(expireTime);
customizeCache.setHitCount(1);
concurrentHashMap.put(key, customizeCache);
}
/**
* 根据key返回数据
* @param key
* @return
*/
public static Object get(String key){
if (StrUtil.isEmpty(key)) {
return null;
}
if (ObjectUtils.isEmpty(concurrentHashMap)) {
return null;
}
if (!concurrentHashMap.containsKey(key)) {
return null;
}
MyCustomizeCache myCustomizeCache = concurrentHashMap.get(key);
if (Objects.isNull(myCustomizeCache)) {
return null;
}
// 惰性删除
long duration = System.currentTimeMillis() - myCustomizeCache.getWriteTime();
long seconds = TimeUnit.MILLISECONDS.toSeconds(duration);
// 过期时间小于 当前时间-写入时间
if (myCustomizeCache.getExpireTime()<=seconds) {
concurrentHashMap.remove(key);
return null;
}
myCustomizeCache.setHitCount(myCustomizeCache.getHitCount()+1);
myCustomizeCache.setLastTime(System.currentTimeMillis());
return myCustomizeCache.getValue();
}
}
- 测试检测工具类是否生效
public class MyCacheTest {
public static void main(String[] args) {
String key = "test1";
MyCacheUtil.put(key,2342134,10);
Object test1 = MyCacheUtil.get(key);
System.out.println("test1 = " + test1);
Object test2 = MyCacheUtil.get(key+1);
System.out.println("test2 = " + test2);
// 打印结果
//test1 = 2342134
//test2 = null
}
}