需求: 实现一个类似session的缓存
问题:
- 什么数据类型是key value,map,这里使用hashmap
- 如何保证缓存过期自定删除,使用定时检查
- 多线程产生数据不一致如何解决:使用synchronized
Cache
package com.springboot.dubbo.model.entity;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* @author WH
* @version 1.0
* @date 2019/10/24 20:51
*/
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Cache {
private String key;
private Object value;
//过期时间
private Long timeout;
}
package com.springboot.dubbo.model.entity;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
/**
* @author WH
* @version 1.0
* @date 2019/10/24 20:54
*/
public class CacheManager {
private Map<String, Cache> cacheMap = new HashMap<>();
//put方法 关闭即过期
public void put(String key, Object value) {
put(key,value,null);
}
//有失效时间
public void put(String key, Object value, Long longout) {
Cache cache = new Cache();
cache.setKey(key);
cache.setValue(value);
//c存入缓存过期时间 单位 毫秒
if (longout != null) {
cache.setTimeout(System.currentTimeMillis() + longout);
}
cacheMap.put(key, cache);
}
//移除缓存方法
public void remove(String key) {
System.out.println(key + "删除成功");
cacheMap.remove(key);
}
//得到缓存对象
public synchronized Object get(String key) {
Cache cache = cacheMap.get(key);
if (cache != null) {
return cache.getValue();
}
return null;
}
//检测缓存是否过期,过期则删除
public synchronized void checkTime() {
System.out.println("检测缓存过期中");
for (String key :cacheMap.keySet()) {
Cache cache = cacheMap.get(key);
if (cache == null) {
break;
}
Long timeout = cache.getTimeout();
Long nowtmie = System.currentTimeMillis();
//如果缓存过期,则移除
if (nowtmie > timeout) {
remove(key);
}
}
}
public static void main(String[] args) {
final CacheManager cacheManager = new CacheManager();
cacheManager.put("name","张三",1999l);
System.out.println("存入缓存");
//保证两个线程一起执行
ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(5);
scheduledExecutorService.schedule(new Runnable() {
@Override
public void run() {
cacheManager.checkTime();
}
}, 1999, TimeUnit.MILLISECONDS);
try {
//线程休眠2s保证两个线程同时执行
Thread.sleep(2000);
} catch (Exception e) {
}
String name = (String)cacheManager.get("name");
System.out.println("缓存数据为:" + name);
}
}
如果get方法不加 synchronized就会出现如下情况
在同一时刻同时操作共享变量出现数据不一致问题