福兮祸所伏,祸兮福所倚
简单业务场景:项目启动的时候 启动多个定时器,实现定时器的增删改。(走高速)
实现CommandLineRunner接口 并标记为spring组件(@Component)
@Component
public class ScheduleConfig implements CommandLineRunner {
private static final Logger LOG = LoggerFactory.getLogger(ScheduleConfig.class);
@Autowired
MeterTaskService meterTaskService;
@Autowired
private CronTaskRegistrar taskRegistrar;
@Autowired
DeviceService deviceService;
@Override
public 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);
@Autowired
private 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;
}
@Override
public 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
@Override
public 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);
}
}
}
代码很纯粹 很好理解 替换相关参数 可以直接拿去用 。
如果觉得有用的话 就可怜可怜小弟吧