SpringBoot中自带了一个能够实现定时任务的注解@Schedule
如果定时任务比较简单,则可以使用SpringBoot中自带的@Schedule,但是如果任务调度很复杂的话,就建议使用Quartz组件了。
说一下这个@Schedule注解怎么用?
基本使用
- 第一步:在一个方法上使用@Schedule,标注这个方法是一个自定义任务
通过该注解的cron属性,指定任务的运行规则
@Slf4j
@Component
public class MyTimeJob {
@Scheduled(cron = "0/1 * * * * *")
public void distanceOffDuty() {
log.info("现在是{},{}",new Date(),"~~~马上就要下班了");
}
}
关于Cron表达式,可以自己学习,
写cron表达式是一件麻烦的事情,就像写正则表达式似的
建议使用工具来生成cron表达式
在线Cron表达式生成器
- 在配置类上通过
@EnableScheduling
开启定时任务配置,开启了此配置后,SpringBoot会自动扫描容器中带有@Schedule注解
注意:将包含@Schedule标注的方法所在的类,设置为Component或Configuration,要让SpringBoot知道这个类
@SpringBootApplication
@EnableScheduling
public class TestQuartzApplication {
public static void main(String[] args) {
SpringApplication.run(TestQuartzApplication.class, args);
}
}
接下来启动程序,就可以看到自定义任务执行了
多线程执行
默认情况下,我们所有自定义的任务是单线程的,多个任务之间排队执行。
例如,我们定义了两个任务:
@Slf4j
@Component
public class MyTimeJob {
@Scheduled(cron = "0/1 * * * * *")
public void distanceOffDuty() {
log.info("现在是{},{}",new Date(),"~~~马上就要下班了");
}
@Scheduled(cron = "0/10 * * * * *")
public void work(){
log.info("又工作(摸鱼)了10秒钟了");
}
}
看控制台这两个任务的执行情况:
如果想要为每一个任务单独开一个线程,异步化操作,效率能提高,不会被阻塞。
此时需要自定义线程池,看操作!
自定义配置类
@Configuration
@EnableScheduling
public class ScheduledConfig implements SchedulingConfigurer {
/**
* 任务执行线程池大小
*/
private static final int TASK_POOL_SIZE = 50;
/**
* 自定义线程前缀
*/
private static final String TASK_THREAD_PREFIX = "scheduling-task-";
@Override
public void configureTasks(ScheduledTaskRegistrar scheduledTaskRegistrar) {
// 创建任务线程池
ThreadPoolTaskScheduler taskPool = new ThreadPoolTaskScheduler();
// 设置线程池大小
taskPool.setPoolSize(TASK_POOL_SIZE);
// 线程前缀名
taskPool.setThreadNamePrefix(TASK_THREAD_PREFIX);
// 初始化
taskPool.initialize();
scheduledTaskRegistrar.setTaskScheduler(taskPool);
}
}
看自定义任务的执行情况:
每次执行任务,都会在线程池中取一个线程来使用