编辑
2023-11-03
学习记录
00
请注意,本文编写于 517 天前,最后修改于 517 天前,其中某些信息可能已经过时。

目录

前提
代码
使用周期线程池好处
可优化点

前提

由于业务需要得实现一个周期性的自动执行任务,之前的话都是在启动类上使用@EnableScheduling,然后定义一个自动任务类,在方法上使用@Scheduled(cron = "${job.archive.cron}"),来实现功能需要,这次就想换种方式实现,采用实现CommandLineRunner接口,这个接口在启动完成后,会自动执行run方法,我准备在run方法里使用周期线程池,来周期性执行。

代码

java
@Component public class AutoReturnTaskRunner implements CommandLineRunner { Logger logger = LoggerFactory.getLogger(this.getClass()); private List<AutoReturnRequest> taskList=new ArrayList<>(); private ScheduledExecutorService scheduler= Executors.newScheduledThreadPool(1); @Resource private IHdpParameterTService iHdpParameterTService; @Resource private IRecReturnLogService iRecReturnLogService; @Resource private IRecMrIndexService iRecMrIndexService; @Override public void run(String... args) throws Exception { // 周期性地检查任务列表并执行任务 scheduler.scheduleAtFixedRate(() -> { logger.info("开始自动执行返修病人的归档和签收操作---------------------"); logger.info("检查数据库配置任务开关是否开启!"); QueryWrapper<HdpParameterTEntity> queryWrapper = new QueryWrapper<>(); queryWrapper.lambda().eq(HdpParameterTEntity::getConfigName, "RETURN_SCHEDULER_ENABLE"); HdpParameterTEntity parameterT = iHdpParameterTService.getOne(queryWrapper); if (ObjectUtil.isNull(parameterT)) { logger.info("未检测开关配置,任务终止---------------------1小时后重试"); } else { if (StrUtil.isNotBlank(parameterT.getConfigValue())) { if ("false".equals(parameterT.getConfigValue())) { logger.info("开关为关闭状态,任务终止---------------------1小时后重试"); } else if ("true".equals(parameterT.getConfigValue())) { logger.info("开关为开启状态,任务开始----------------------"); if (taskList.isEmpty()) { // 从数据库中获取任务并添加到列表中 taskList = iRecReturnLogService.getAutoTaskList(); if (CollUtil.isEmpty(taskList)) { logger.info("数据库中还未发现返修后需要自动归档、签收数据,1小时后重试"); } } else { // 执行任务列表中的任务 Iterator<AutoReturnRequest> iterator = taskList.iterator(); while (iterator.hasNext()) { AutoReturnRequest task = iterator.next(); Date now = new Date(); if (now.compareTo(task.getReturnTimeEnd()) > 0) { //当前时间大于该患者归档截止 QueryWrapper<RecMrIndexEntity> queryrIndexWrapper = new QueryWrapper(); queryrIndexWrapper.lambda().eq(RecMrIndexEntity::getPatientId, task.getPatientId()).eq(RecMrIndexEntity::getVisitNo, task.getVisitNo()); RecMrIndexEntity entity = iRecMrIndexService.getOne(queryrIndexWrapper); if (entity.getPaperReceiveStatus() == 0 && entity.getArchiveStatus() == 0) { entity.setMrStatus("A"); entity.setArchiveTime(now); if (entity.getFirstArchiveTime() == null) { entity.setFirstArchiveTime(now); } entity.setArchiveDoctorId("9999"); entity.setArchiveDoctor("自动任务"); entity.setArchiveStatus(1); entity.setPaperReceiveStatus(1); entity.setReceiveTime(now); entity.setReceiveDoctorId("9999"); entity.setReceiveDoctor("自动任务"); } boolean result = iRecMrIndexService.updateById(entity); if (result) { iterator.remove(); } } } logger.info("当前所有任务执行完毕-------------1小时后再次运行任务"); } } else { logger.info("开关配置错误,任务终止---------------------1小时后重试"); } } else { logger.info("未检测开关配置,任务终止---------------------1小时后重试"); } } }, 0, 60, TimeUnit.MINUTES); // 每1小时执行一次任务 } public void stop() { scheduler.shutdown(); } }

使用周期线程池好处

可以实现对任务执行的精准控制,编写控制方法后,调用stop和run方法就可以在前台页面通过按钮对任务执行状况进行精准控制.

可优化点

可以将经过某些操作后需要处理的任务添加到redis中,处理列表为空的先去redis中获取,避免老是查询数据库,提高执行的效率

本文作者:Weee

本文链接:

版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!