spring简单集成定时任务

直接使用@EnableScheduling开启定时任务,使用@Scheduled(cron = "")来标注任务马上就可以完成一个简单的定时任务了,这里就不贴上代码了

spring动态实现定时任务

创建一个SchedulingConfig配置类来初始化定时任务的线程池的大小和名称等信息

// 开启定时任务
@EnableScheduling 
@Configuration
public class SchedulingConfig {

    @Bean
    public TaskScheduler taskScheduler() {
        // 创建任务调度线程池
        ThreadPoolTaskScheduler taskScheduler = new ThreadPoolTaskScheduler();
        // 初始化线程池数量
        taskScheduler.setPoolSize(4);
        // 是否将取消后的任务,从队列中删除
        taskScheduler.setRemoveOnCancelPolicy(true);
        // 设置线程名前缀
        taskScheduler.setThreadNamePrefix("TaskSchedulerThreadPool-");
        return taskScheduler;
    }
}

查找代码可以看见sringbot中有相关的定时任务注册类,需要实现SchedulingConfigurer 类来进行注册定时任务,configureTasks在项目初始化的时候会进行执行然后通ScheduledTaskRegistrar 用来注册定时任务,这里想进行动态的增加不太现实,我们可以对这个类做一个改变使我们可以在项目启动之后获取到ScheduledTaskRegistrar这个类,代码如下:

@Component
public class ReportAutoTask implements SchedulingConfigurer {

	private ScheduledTaskRegistrar scheduledTaskRegistrar;

	/**
     * 根据taskId来储存指定的任务
     */
    private Map<String, ScheduledTask> scheduledTaskMap = new ConcurrentHashMap<>(16);

    /**
     * 定时任务注册(这个方法会在启动的时候进行执行)
     *
     * @param scheduledTaskRegistrar
     */
    @Override
    public void configureTasks(ScheduledTaskRegistrar scheduledTaskRegistrar) {
     	this.scheduledTaskRegistrar = scheduledTaskRegistrar;
    }
    
    public ScheduledTaskRegistrar getScheduledTaskRegistrar() {
        return scheduledTaskRegistrar;
    }

    public void setScheduledTaskRegistrar(ScheduledTaskRegistrar scheduledTaskRegistrar) {
        this.scheduledTaskRegistrar = scheduledTaskRegistrar;
    }

    public Map<String, ScheduledTask> getScheduledTaskMap() {
        return scheduledTaskMap;
    }

    public void setScheduledTaskMap(Map<String, ScheduledTask> scheduledTaskMap) {
        this.scheduledTaskMap = scheduledTaskMap;
    }
}

使用ScheduledTaskRegistrar来注册定时任务

红色的是这个类新增定时任务的方法,这里主要是用addCronTask这个方法来新增定时任务

java 动态任务调度 springboot动态任务调度_spring

可以看到addCronTask上图中需要一个Runnable和一个表达式的参数,这两个参数也是创建一个CronTask的要求,所以我们首先去创建一个Runnable,代码中是我自己创建的一些业务可以忽略,主要的方法就是一个run方法

@Component
@Slf4j
public class ReportAutoRunnable implements Runnable {

    /**
     * reportAutoDTO
     */
    private ReportAutoDTO reportAutoDTO;

    public ReportAutoDTO getReportAutoDTO() {
        return reportAutoDTO;
    }

    public void setReportAutoDTO(ReportAutoDTO reportAutoDTO) {
        this.reportAutoDTO = reportAutoDTO;
    }

    @Autowired
    private ReportAutoService reportAutoService;

    @Override
    public void run() {
        String name = Thread.currentThread().getName();
        try {
            log.info("定时任务开始执行 任务id:{} ,线程名称:{}", reportAutoDTO.getId(),name);
            reportAutoService.autoReport(reportAutoDTO);
            log.info("定时任务执行完毕 任务id:{} ,线程名称:{}", reportAutoDTO.getId(),name);
        } catch (Exception ex) {
            log.info("定时任务执行出现异常 任务id:{} ,异常信息:{}", reportAutoDTO.getId(),ex.getMessage());
        }
    }
}

自定义CronTask

创建完Runnable后可以创建一个CronTask,我是继承了一下CronTask类增加了两个属性一个id,一个名称

public class ReportAutoCronTask extends CronTask {
    /**
     * 任务id
     */
    private String taskId;

    /**
     * 任务名称
     */
    private String taskName;


    public ReportAutoCronTask(Runnable runnable, String expression) {
        super(runnable, expression);
    }

    public ReportAutoCronTask(Runnable runnable, CronTrigger cronTrigger) {
        super(runnable, cronTrigger);
    }

    public ReportAutoCronTask(Runnable runnable, String expression,String taskId,String taskName){
        super(runnable, expression);
        this.taskId = taskId;
        this.taskName = taskName;
    }

    public String getTaskId() {
        return taskId;
    }

    public void setTaskId(String taskId) {
        this.taskId = taskId;
    }

    public String getTaskName() {
        return taskName;
    }

    public void setTaskName(String taskName) {
        this.taskName = taskName;
    }
}

注册并启动定时任务

下面这一块代码就可以成功的注册一个定时任务

// 每30秒执行一次
 String expression ="0/30 0 0 * ?";
 // 创建定时任务
ReportAutoCronTask reportAutoCronTask = new ReportAutoCronTask(reportAutoRunnable, expression, "1111", "任务名称");
scheduledTaskRegistrar.addCronTask(reportAutoCronTask);
 // 启动定时任务
ScheduledTask scheduledTask = scheduledTaskRegistrar.scheduleCronTask(reportAutoCronTask);reportAutoCronTask.setFlag(true);
scheduledTaskMap.put("1111", scheduledTask);

关闭指定的定时任务

遍历之前储存任务的集合直接调用cancel()就可以直接关闭带任务,如果需要删除的话就直接删除掉map中的定时任务就可以,想修改可以删除掉再重新新增

for (Map.Entry<String, ScheduledTask> scheduledTaskEntry : scheduledTaskMap.entrySet()) {
                if (scheduledTaskEntry.getKey().equals(reportAutoDTO.getId())) {
                    // 停止定时任务
                    scheduledTaskEntry.getValue().cancel();
                }
            }