首先实现定时任务读取数据库信息到内存:
public class ScheduledTask {
@Autowired
private TestMapper testMapper;
@Autowired
private ScheduledTaskImpl scheduledTaskImpl;
/**
* Cron表达式由6~7项组成,中间用空格分开。从左到右依次是:秒、分、时、日、月、周几、年(可省略)。值可以是数字,也可以是以下符号:
* :所有值都匹配
* ? :无所谓,不关心,通常放在“周几”里
* , :或者
* / :增量值
* - :区间
*/
private static ExecutorService executorService;
public static ExecutorService getExecutorService() {
if (null == executorService) {
executorService = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());
}
return executorService;
}
@Scheduled(cron = "0 5/5 * * * ? ")
public void executeCompanyCodeTask() {
getExecutorService().execute(new Runnable() {
@Override
public void run() {
try {
Map<Long, Test> idMap = new HashMap<>();
List<Test> list = testMapper.selectAll();
for(Test test: list){
idMap.put(test.getId(), object);
}
scheduledTaskImpl.setIdMap(idMap);
} catch (Exception e) {
e.printStackTrace();
log.error("更新信息出错", e);
}
}
});
}
}
接下来就是从内存中取数据:
public class ScheduledTaskImpl {
@Autowired
private TestfMapper testMapper;
private Map<Long, Test> idMap = new HashMap<>();
private ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
public void setIdMap(Map idMap){
lock.writeLock().lock();//上写锁,不允许其他线程读也不允许写
this.idMap = idMap;
lock.writeLock().unlock();//释放写锁
}
public Test getById(Long id){
Test test = null;
lock.readLock().lock();//首先开启读锁,从缓存中去取
try {
test = idMap.get(id);
if (test == null) {//如果缓存中没有释放读锁,上写锁
lock.readLock().unlock();
lock.writeLock().lock();
try {
if(test == null){
test = testMapper.selectById(id);
if (test == null) {
throw new RuntimeException("数据不存在");
}
idMap.put(id, test);
}
}finally {
lock.writeLock().unlock();//释放写锁
}
lock.readLock().lock();//然后再上读锁
}
}catch (Exception e) {
log.error("根据id获取数据出错," + e.getMessage());
} finally {
lock.readLock().unlock();//最后释放读锁
}
return test;
}
}
参考博客:
1.https://www.jianshu.com/p/840b55ef4186
2.https://www.cnblogs.com/zzlp/p/5174745.html