SpringBoot下使用定时任务的几种方式

本文简单的对springboot下面几种定时任务的实现方式

1.定时器Scheduled

  • springboot web模块依赖整合好了定时器的依赖
<dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-web</artifactId>
</dependency>

新建Task类,加上注解Component,主函数加上@EnableScheduling

@Component
public class Task {
    // @Scheduled(cron = "*/5 * * ? * *")
    /**
     * fixedRate上一个调用开始后再次调用的延时(不用等待上一次调用完成)
     */
    // @Scheduled(fixedRate = 1 * 1000)

    /**
     * 等到方法执行完成后延迟配置的时间再次执行该方法
     */
    @Scheduled(fixedDelay = 1 * 1000)
    public void Task() {
        try {
            Thread.sleep(2000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(System.currentTimeMillis());
    }
}

这是一种非常简单的实现方式。但是有个缺点。如果多个定时任务一起执行,实际上是一个个任务同一个线程搞定的,如果其中一个出了异常,串行就走不下去了。

1550219739697.png

2.开启异步

新增异步配置类AsyncConfig

public class AsyncConfig {
     /*
   	 此处成员变量应该使用@Value从配置中读取
     */
    private int corePoolSize = 10;
    private int maxPoolSize = 200;
    private int queueCapacity = 10;
    
    @Bean
    public Executor taskExecutor() {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        executor.setCorePoolSize(corePoolSize);
        executor.setMaxPoolSize(maxPoolSize);
        executor.setQueueCapacity(queueCapacity);
        executor.initialize();
        return executor;
    }

}

主函数增加@EnableAsync,表示开启异步支持。

任务方法里面添加@Async,表示使用异步线程执行定时任务

以上都是定时任务的基本操作,不支持动态修改cron表达式,需要修改并重启应用。

3.SchedulingConfigurer

实现该接口可以实现定时任务动态修改。可以把cron表达式保存到数据库中。动态修改可以热加载定时器任务。

ps: 修改后不会马上生效,需要等待下个周期才会更新 cron,意味下次还是原来时间触发。下下次才生效修改的。

@Configuration
@EnableScheduling
public class CompleteScheduleConfig implements SchedulingConfigurer {
    @Autowired
    private CronMapper cronMapper;

    @Override
    public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {
        taskRegistrar.addTriggerTask(
                //1.添加任务内容(Runnable)
                () -> System.out.println("执行定时任务2: " + LocalDateTime.now().toLocalTime()),
                //2.设置执行周期(Trigger)
                triggerContext -> {
                    //2.1 从数据库获取执行周期。修改数据库cron表达式即可(修改过后,下一次执行任务更新cron)。多个定时任务可以添加id字段区分重复一下代码即可。
                    String cron = cronMapper.getCron();

                    //2.2 合法性校验.
                    if (StringUtils.isEmpty(cron)) {
                        // Omitted Code ..
                    }
                    //2.3 返回执行周期(Date)
                    return new CronTrigger(cron).nextExecutionTime(triggerContext);
                }
        );


    }
}

数据库就一个单独的cron字段。

测试动态修改cron,执行定时任务的触发时间也相应改变。

上次更新时间: 2024/5/7 05:59:02