SpringBoot动态增删定时调度

Spring 4和SpringBoot 1.5中常见的使用定时调度方式

@Scheduled(cron = "1 * * * * ?")
public void check() {
    try {
        System.out.printf("Time: %s, thread: %s.%n",
                DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss").format(LocalDateTime.now()), 
                Thread.currentThread().getName());
        TimeUnit.SECONDS.sleep(30);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
}

最近项目中需要让用户在前端配置定时触发任务,由于触发的任务数量并不多,且应用不是分布式程序,所以考虑就不考虑使用quartz,简单使用Spring的Schedule来实现。

通过ScheduleConfig启用Schedule并配置执行任务的执行器(实现TaskScheduler/ScheduledExecutorService对象,如果都没有则创建一个只有一个线程的线程池[org.springframework.scheduling.config.ScheduledTaskRegistrar#scheduleTasks])以及对外暴露ScheduledTaskRegistrar。

@SpringBootConfiguration
@EnableScheduling
public class ScheduleConfig implements SchedulingConfigurer {

    private ScheduledTaskRegistrar taskRegistrar;

    @Override
    public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {
        this.taskRegistrar = taskRegistrar;
        taskRegistrar.setScheduler(taskExecutor());
    }

    @Bean(destroyMethod = "shutdown")
    public ThreadPoolExecutor taskExecutor() {
        return (ThreadPoolExecutor) Executors.newScheduledThreadPool(20);
    }

    public ScheduledTaskRegistrar getTaskRegistrar() {
        return taskRegistrar;
    }
}

在service中通过ScheduleConfig获取到ScheduledTaskRegistrar,通过ScheduledTaskRegistrar的scheduleCronTask方法可以添加新任务,返回值是一个ScheduledTask对象,通过该对象的cancel方法可以取消该任务的执行,再拿一个map保存任务的id和ScheduledTask对象即可,demo如下:

@Service
public class TaskService {

    private final ScheduleConfig scheduleConfig;
    // 保存已经配置的定时任务
    private final Map<Integer, ScheduledTask> scheduledTasks = new HashMap<>();

    public TaskService(ScheduleConfig scheduleConfig) {
        this.scheduleConfig = scheduleConfig;
    }
    
    private ScheduledTaskRegistrar getRegistrar() {
        return scheduleConfig.getTaskRegistrar();
    }

    /**
     * 处理前端封装的参数 
     */
    public synchronized void processTask(XmonAlertTaskWrapper wrapper) {
        int id = wrapper.getId();
        if ("add".equals(wrapper.getAction())) {
            CronTask cronTask = new CronTask(new XmonAlert(wrapper.getMsg()), wrapper.getExpression());
            if (scheduledTasks.containsKey(id)) {
                // map中存在表示需要修改该任务,先取消之前的任务
                scheduledTasks.get(id).cancel();
            }
            // 添加新的任务
            ScheduledTask scheduledTask = getRegistrar().scheduleCronTask(cronTask);
            scheduledTasks.put(id, scheduledTask);
            System.out.println("添加" + wrapper + "成功.");
        } else {
            // 删除任务
            if (scheduledTasks.containsKey(id)) {
                // 取消任务的执行
                scheduledTasks.get(id).cancel();
                // map中删除该任务
                scheduledTasks.remove(id);
            }
            System.out.println("删除" + wrapper + "成功.");
        }
    }

    /**
     * 定时执行的任务
     */
    static class XmonAlert implements Runnable {

        private final String msg;

        public XmonAlert(String msg) {
            this.msg = msg;
        }

        @Override
        public void run() {
            try {
                System.out.printf("Time: %s, thread: %s, msg: %s.%n",
                        DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss").format(LocalDateTime.now()), Thread.currentThread().getName(), msg);
                TimeUnit.SECONDS.sleep(30);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值