说明:
有时候经常需要进行初始化操作,数据量比较大的情况下呢,还需要分页,现记录一下方便下次用到。
如果需要异步操作的话,那最好定义一个线程池。
如果是分布式集群部署,那还得用个分布式锁
步骤如下:
1、配置线程池
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
/**
* 线程池配置
* @author ppp
* @date 2024/7/26
*/
@Configuration
public class ThreadPoolConfig {
@Bean
public ThreadPoolExecutor initDataThreadPool() {
int availableProcessors = Runtime.getRuntime().availableProcessors();
return new ThreadPoolExecutor(
1,
availableProcessors * 2,
1000L,
TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<>(10000),
new WorkerThreadFactory(),
new ThreadPoolExecutor.CallerRunsPolicy());
}
public static class WorkerThreadFactory implements ThreadFactory {
private final ThreadGroup group;
private final AtomicInteger threadNumber = new AtomicInteger(1);
private final String namePrefix;
public WorkerThreadFactory() {
SecurityManager s = System.getSecurityManager();
group = (s != null) ? s.getThreadGroup() :
Thread.currentThread().getThreadGroup();
namePrefix = "initData-worker-thread-";
}
@Override
public Thread newThread(Runnable r) {
Thread t = new Thread(group, r,
namePrefix + threadNumber.getAndIncrement(),
0);
if (t.isDaemon()) {
t.setDaemon(false);
}
return t;
}
}
}
2、初始化操作类:
import cn.hutool.core.date.DateField;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import com.github.pagehelper.PageInfo;
import com.lititi.exams.web.manager.MomentUpdateMangerService;
import com.lititi.exams.web.pojo.MomentDetailResponseVO;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.util.ObjectUtils;
import javax.annotation.Resource;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;
/**
* 朋友圈内容数据初始化
* @author ppp
* @date 2024/7/26
*/
@Component
public class DataInitHandler implements ApplicationRunner {
private final static Logger logger = LoggerFactory.getLogger(DataInitHandler.class);
@Resource
private ThreadPoolExecutor initDataThreadPool;
@Resource
private RedisTemplate<String, List<MomentDetailResponseVO>> redisTemplate;
@Resource
private MomentUpdateMangerService momentUpdateMangerService;
@Override
public void run(ApplicationArguments args) {
logger.info("加载最近十天的数据到redis");
Date date = new Date();
DateTime startTime = DateUtil.beginOfDay(date);
Date newDate = DateUtil.offset(date, DateField.DAY_OF_MONTH, 10);
DateTime endTimes = DateUtil.endOfDay(newDate);
AtomicInteger pageNo = new AtomicInteger(1);
int pageSize = 200;
initDataThreadPool.execute(()->{
List<MomentDetailResponseVO> list = momentUpdateMangerService.getPageList(startTime, endTimes, pageNo.get(), pageSize);
PageInfo<MomentDetailResponseVO> page = new PageInfo<>(list);
saveDataToRedis(list);
for (int i = 1; i < page.getPages(); i++) {
pageNo.getAndIncrement();
List<MomentDetailResponseVO> voList = momentUpdateMangerService.getPageList(startTime, endTimes, pageNo.get(), pageSize);
saveDataToRedis(voList);
}
});
logger.info("加载最近十天的数据到redis完成——");
}
/**
* 保存数据到redis
* @param voList 列表数据
*/
private void saveDataToRedis(List<MomentDetailResponseVO> voList) {
if (!ObjectUtils.isEmpty(voList)) {
Map<String, List<MomentDetailResponseVO>> map = voList.stream().collect(Collectors.groupingBy(MomentDetailResponseVO::getUserId));
map.forEach((k,v)->{
redisTemplate.opsForValue().set(k, v, 30, TimeUnit.MINUTES);
});
}
}
}