当前位置: 代码迷 >> 综合 >> 利用spring自带的定时器 实现动态定时器的增删改
  详细解决方案

利用spring自带的定时器 实现动态定时器的增删改

热度:78   发布时间:2024-02-07 03:32:31.0

福兮祸所伏,祸兮福所依

 简单业务场景:项目启动的时候 启动多个定时器。(走高速)


实现CommandLineRunner接口  并标记为spring组件(@Component)@Component
public class ScheduleConfig implements CommandLineRunner {private static final Logger LOG = LoggerFactory.getLogger(ScheduleConfig.class);@AutowiredMeterTaskService meterTaskService;@Autowiredprivate CronTaskRegistrar taskRegistrar;@AutowiredDeviceService deviceService;@Overridepublic void run(String... args) throws Exception {LOG.debug("进入ScheduleConfig.....");List<MeterTask> meterTasks = meterTaskService.findAllCron();if (meterTasks.size() > 0) {for (MeterTask meterTask : meterTasks) {if (!meterTask.getIsSuccess()) {// 每个定时器所对应的业务逻辑处理线程   SchedulingRunnable task = new SchedulingRunnable(meterTask.getCron(), meterTask.getMeterId(), meterTaskService, deviceService);// 将当前线程和标识以及cron表达式添加到CronTaskRegistrar中taskRegistrar.addCronTask(meterTask.getMeterId(), task, meterTask.getCron());}}}}
}

看一下其中的taskRegistrar和SchedulingRunnable到底是什么鬼。

taskRegistrar

DisposableBean主要处理bean的  这里通过DisposableBean的destroy方法是销毁定时器@Component
public class CronTaskRegistrar implements DisposableBean {// 线程安全map去存储定时器private final Map<Integer, ScheduledTask> scheduledTasks = new ConcurrentHashMap<>(16);@Autowiredprivate TaskScheduler taskScheduler;// 添加定时器   cronId为定时器的唯一标识(根据你的业务去选择什么作为唯一标识)// task对应的线程   cronExpression为cron的表达式public void addCronTask(Integer cronId,Runnable task, String cronExpression) {addCronTask(cronId,new CronTask(task, cronExpression));}public void addCronTask(Integer cronId,CronTask cronTask) {if (cronTask != null) {if (this.scheduledTasks.containsKey(cronId)) {removeCronTask(cronId);}this.scheduledTasks.put(cronId, scheduleCronTask(cronTask));}}// 移除某个定时器public void removeCronTask(Integer cronId) {ScheduledTask scheduledTask = this.scheduledTasks.remove(cronId);if (scheduledTask != null) {scheduledTask.cancel();}}// 核心代码   public ScheduledTask scheduleCronTask(CronTask cronTask) {ScheduledTask scheduledTask = new ScheduledTask();scheduledTask.future = this.taskScheduler.schedule(cronTask.getRunnable(), cronTask.getTrigger());return scheduledTask;}@Overridepublic void destroy() throws Exception {for (ScheduledTask task : this.scheduledTasks.values()) {task.cancel();}this.scheduledTasks.clear();}
}

 SchedulingRunnable

/*** @author peanut*/
public class SchedulingRunnable implements Runnable{private static final Logger LOG = LoggerFactory.getLogger(SchedulingRunnable.class);private String cron;private Integer meterId;private MeterTaskService meterTaskService;private DeviceService deviceService;public SchedulingRunnable(String cron, Integer meterId, MeterTaskService meterTaskService, DeviceService deviceService) {this.cron = cron;this.meterId = meterId;this.meterTaskService = meterTaskService;this.deviceService = deviceService;}@SneakyThrows@Overridepublic void run() {// 执行任务System.out.println(meterId + "的表达式是:" + cron);System.out.println("执行任务");// 清零try {deviceService.clear(meterId + "");} catch (ConnectionException e) {LOG.error("当前的异常是:{}" + e.getMessage());throw new ConnectionException("请检查端口链接");} catch (Exception e) {throw new Exception("请检查端口链接");}// 如果是单次的话  就修改状态MeterTask meterTask = meterTaskService.findByMeterId(meterId);if (MeterConstant.BIT_ZERO_FLAG.equals(meterTask.getType())) {meterTaskService.updateByMeterId(meterId);}}
}
/*** @author peanut*/
public final class ScheduledTask {public volatile ScheduledFuture<?> future;/*** 取消定时任务*/public void cancel() {ScheduledFuture<?> future = this.future;if (future != null) {future.cancel(true);}}
}

代码很纯粹  很好理解   替换相关参数  可以直接拿去用 。

  相关解决方案