Springboot定时任务 @Scheduled
我们在平常项目开发中,经常会用到周期性定时任务,这个时候使用定时任务就能很方便的实现。在SpringBoot中用得最多的就是Schedule。
一、SpringBoot集成Schedule
1、依赖配置
由于Schedule就包含在spring-boot-starter中,所以无需引入其他依赖。
2、启用定时任务
在启动类或者配置类上增加@EnableScheduling注解。
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.scheduling.annotation.EnableScheduling;
@EnableScheduling
@SpringBootApplication
public class DemoApplication {
public static void main(String[] args) {SpringApplication.run(DemoApplication.class, args);}
}
3、添加定时任务
Schdule支持cron表达式、固定间隔时间、固定频率三种调度方式。
1)cron表达式定时任务
与Linux下定时任务用到的Cron表达式一样。
字段 | 允许值 | 允许的特殊字符 |
---|---|---|
秒(Seconds) | 0~59的整数 | , - * / 四个字符 |
分(Minutes) | 0~59的整数 | , - * / 四个字符 |
小时(Hours) | 0~23的整数 | , - * / 四个字符 |
日期(DayofMonth) | 1~31的整数(但是你需要考虑该月的天数) | ,- * ? / L W C 八个字符 |
月份(Month) | 1~12的整数或者 JAN-DEC | , - * / 四个字符 |
星期(DayofWeek) | 1~7的整数或者 SUN-SAT (1=SUN) | , - * ? / L C # 八个字符 |
年(可选,留空)(Year) | 1970~2099 | , - * / 四个字符 |
@Component
@EnableScheduling
public class MyCronTask {
private static final Logger logger = LoggerFactory.getLogger(MyCronTask.class);
@Scheduled(cron = "0/1 * * * * *")void cronSchedule(){logger.info("cron schedule execute");}
}
PS:Cron表达式方式配置的定时任务如果其执行时间超过调度频率时,调度器会在下个执行周期执行。如第一次执行从第0秒开始,执行时长3秒,则下次执行为第4秒。
2)固定间隔定时任务
下一次的任务执行时间是从上一次定时任务结束时间开始计算。
@Scheduled(fixedDelay = 2)
void fixedDelaySchedule() throws Exception{Thread.sleep(2000);logger.info("fixed delay schedule execute");
}
输出:
2020-04-23 23:11:54.362 INFO 85325 --- [ scheduling-1] com.springboot.study.tasks.MyCronTask : fixed delay schedule execute 2020-04-23 23:11:58.365 INFO 85325 --- [ scheduling-1] com.springboot.study.tasks.MyCronTask : fixed delay schedule execute 2020-04-23 23:12:02.372 INFO 85325 --- [ scheduling-1] com.springboot.study.tasks.MyCronTask : fixed delay schedule execute 2020-04-23 23:12:06.381 INFO 85325 --- [ scheduling-1] com.springboot.study.tasks.MyCronTask : fixed delay schedule execute
3)固定频率定时任务
按照指定频率执行任务
@Scheduled(fixedRate = 2000)
void fixedRateSchedule() throws Exception{Thread.sleep(3000);logger.info("fixed rate schedule execute");
}
输出:
2020-04-23 23:16:14.750 INFO 85328 --- [ scheduling-1] com.springboot.study.tasks.MyCronTask : fixed rate schedule execute 2020-04-23 23:16:17.754 INFO 85328 --- [ scheduling-1] com.springboot.study.tasks.MyCronTask : fixed rate schedule execute 2020-04-23 23:16:20.760 INFO 85328 --- [ scheduling-1] com.springboot.study.tasks.MyCronTask : fixed rate schedule execute 2020-04-23 23:16:23.760 INFO 85328 --- [ scheduling-1] com.springboot.study.tasks.MyCronTask : fixed rate schedule execute 2020-04-23 23:16:26.764 INFO 85328 --- [ scheduling-1] com.springboot.study.tasks.MyCronTask : fixed rate schedule execute
PS:当方法的执行时间超过任务调度频率时,调度器会在当前方法执行完成后立即执行下次任务。
二、配置多个定时任务并发执行
1、并行or串行?
缺省状态下,当我们没有给定时任务配置线程池时,Schedule是串行执行,如下:
@Component
@EnableScheduling
public class MyCronTask {
private static final Logger logger = LoggerFactory.getLogger(MyCronTask.class);@Scheduled(fixedDelay = 2000)void task1Schedule() throws Exception{Thread.sleep(2000);logger.info("task1 execute");}
@Scheduled(fixedDelay = 2000)void task2Schedule() throws Exception{Thread.sleep(2000);logger.info("task2 execute");}
@Scheduled(fixedDelay = 2000)void task3Schedule() throws Exception{Thread.sleep(2000);logger.info("task3 execute");}
}
输出:
2020-04-23 23:19:46.970 INFO 85332 --- [ scheduling-1] com.springboot.study.tasks.MyCronTask : task1 execute 2020-04-23 23:19:48.973 INFO 85332 --- [ scheduling-1] com.springboot.study.tasks.MyCronTask : task2 execute 2020-04-23 23:19:50.974 INFO 85332 --- [ scheduling-1] com.springboot.study.tasks.MyCronTask : task3 execute 2020-04-23 23:19:52.978 INFO 85332 --- [ scheduling-1] com.springboot.study.tasks.MyCronTask : task1 execute 2020-04-23 23:19:54.984 INFO 85332 --- [ scheduling-1] com.springboot.study.tasks.MyCronTask : task2 execute 2020-04-23 23:19:56.984 INFO 85332 --- [ scheduling-1] com.springboot.study.tasks.MyCronTask : task3 execute
可以看出来只有一个线程穿行执行所有定时任务。
2、Schedule并行执行配置
定时调度的并行化,有两种配置方式:
1)修改任务调度器默认使用的线程池:添加一个configuration,实现SchedulingConfigurer接口就可以了。
@Configuration
public class ScheduleConfig implements SchedulingConfigurer{
@Overridepublic void configureTasks(ScheduledTaskRegistrar taskRegistrar) {taskRegistrar.setTaskScheduler(getTaskScheduler());}
@Beanpublic TaskScheduler getTaskScheduler() {ThreadPoolTaskScheduler taskScheduler = new ThreadPoolTaskScheduler();taskScheduler.setPoolSize(3);taskScheduler.setThreadNamePrefix("myworker-");taskScheduler.setWaitForTasksToCompleteOnShutdown(true);return taskScheduler;}
}
再次执行后,输出:
2020-04-23 23:33:14.197 INFO 85461 --- [ myworker-2] com.springboot.study.tasks.MyCronTask : task2 execute 2020-04-23 23:33:14.197 INFO 85461 --- [ myworker-1] com.springboot.study.tasks.MyCronTask : task1 execute 2020-04-23 23:33:14.197 INFO 85461 --- [ myworker-3] com.springboot.study.tasks.MyCronTask : task3 execute 2020-04-23 23:33:18.203 INFO 85461 --- [ myworker-2] com.springboot.study.tasks.MyCronTask : task2 execute 2020-04-23 23:33:18.203 INFO 85461 --- [ myworker-3] com.springboot.study.tasks.MyCronTask : task1 execute 2020-04-23 23:33:18.204 INFO 85461 --- [ myworker-1] com.springboot.study.tasks.MyCronTask : task3 execute 2020-04-23 23:33:22.208 INFO 85461 --- [ myworker-1] com.springboot.study.tasks.MyCronTask : task3 execute 2020-04-23 23:33:22.208 INFO 85461 --- [ myworker-2] com.springboot.study.tasks.MyCronTask : task2 execute 2020-04-23 23:33:22.208 INFO 85461 --- [ myworker-3] com.springboot.study.tasks.MyCronTask : task1 execute
2)直接将任务交给一步线程池处理:启用@EnableAsync注解,并在每一个定时任务方法上使用@Async注解。
@Component
@EnableScheduling
@EnableAsync
@Async
public class MyCronTask {
private static final Logger logger = LoggerFactory.getLogger(MyCronTask.class);
@Scheduled(fixedDelay = 2000)void task1Schedule() throws Exception{Thread.sleep(2000);logger.info("task1 execute");}
@Scheduled(fixedDelay = 2000)void task2Schedule() throws Exception{Thread.sleep(2000);logger.info("task2 execute");}
@Scheduled(fixedDelay = 2000)void task3Schedule() throws Exception{Thread.sleep(2000);logger.info("task3 execute");}
}
输出如下:
2020-04-23 23:38:00.614 INFO 85468 --- [ task-1] com.springboot.study.tasks.MyCronTask : task1 execute 2020-04-23 23:38:00.614 INFO 85468 --- [ task-3] com.springboot.study.tasks.MyCronTask : task3 execute 2020-04-23 23:38:00.614 INFO 85468 --- [ task-2] com.springboot.study.tasks.MyCronTask : task2 execute 2020-04-23 23:38:02.620 INFO 85468 --- [ task-4] com.springboot.study.tasks.MyCronTask : task1 execute 2020-04-23 23:38:02.620 INFO 85468 --- [ task-5] com.springboot.study.tasks.MyCronTask : task2 execute 2020-04-23 23:38:02.620 INFO 85468 --- [ task-6] com.springboot.study.tasks.MyCronTask : task3 execute
有上面输出可以看出来这种方式对于每一次定时任务的执行都会创建新的线程,这样对内存资源是一种浪费,严重情况下还会导致服务挂掉,因此为了更好控制线程的使用,我们可以自定义线程池。
首先配置线程池:
@Configuration
public class MyTaskExecutor {
@Bean(name = "myExecutor")public TaskExecutor getMyExecutor() {ThreadPoolTaskExecutor taskExecutor = new ThreadPoolTaskExecutor();taskExecutor.setCorePoolSize(3);taskExecutor.setMaxPoolSize(10);taskExecutor.setQueueCapacity(20);taskExecutor.setThreadNamePrefix("myExecutor-");taskExecutor.initialize();return taskExecutor;}
}
使用我们自己的线程池:
@Component
@EnableScheduling
@EnableAsync
@Async("myExecutor")
public class MyCronTask {
private static final Logger logger = LoggerFactory.getLogger(MyCronTask.class);
@Scheduled(fixedDelay = 2000)void task1Schedule() throws Exception{Thread.sleep(2000);logger.info("task1 execute");}
@Scheduled(fixedDelay = 2000)void task2Schedule() throws Exception{Thread.sleep(2000);logger.info("task2 execute");}
@Scheduled(fixedDelay = 2000)void task3Schedule() throws Exception{Thread.sleep(2000);logger.info("task3 execute");}
}
输出:
2020-04-23 23:46:47.404 INFO 85488 --- [ myExecutor-1] com.springboot.study.tasks.MyCronTask : task1 execute 2020-04-23 23:46:47.404 INFO 85488 --- [ myExecutor-3] com.springboot.study.tasks.MyCronTask : task3 execute 2020-04-23 23:46:47.404 INFO 85488 --- [ myExecutor-2] com.springboot.study.tasks.MyCronTask : task2 execute 2020-04-23 23:46:49.404 INFO 85488 --- [ myExecutor-3] com.springboot.study.tasks.MyCronTask : task2 execute 2020-04-23 23:46:49.404 INFO 85488 --- [ myExecutor-2] com.springboot.study.tasks.MyCronTask : task3 execute 2020-04-23 23:46:49.404 INFO 85488 --- [ myExecutor-1] com.springboot.study.tasks.MyCronTask : task1 execute 2020-04-23 23:46:51.405 INFO 85488 --- [ myExecutor-2] com.springboot.study.tasks.MyCronTask : task2 execute 2020-04-23 23:46:51.405 INFO 85488 --- [ myExecutor-3] com.springboot.study.tasks.MyCronTask : task1 execute 2020-04-23 23:46:51.405 INFO 85488 --- [ myExecutor-1] com.springboot.study.tasks.MyCronTask : task3 execute
Springboot定时任务 @Scheduled相关推荐
- SpringBoot定时任务@Scheduled注解详解
SpringBoot定时任务@Scheduled注解详解 项目开发中,经常会遇到定时任务的场景,Spring提供了@Scheduled注解,方便进行定时任务的开发 概述 要使用@Scheduled注解 ...
- SpringBoot定时任务(@Scheduled)说明
转载文章:http://blog.csdn.net/loongshawn/article/details/50663393 1. 定时任务实现方式 定时任务实现方式: Java自带的java.util ...
- SpringBoot定时任务 @Scheduled详解
博主在最近的开发中又遇到了关于定时调度的开发任务,在定时调度其实有很多的第三方平台可以接入,但是其实在SpringBoot有自带的定时任务注解@Scheduled.@Scheduled可以通过注解配置 ...
- springboot 定时任务@Scheduled cron表达式、fixedRate、fixedDelay、initialDelay和@EnableAsync、@Async的结合使用
定时任务几种形式 1,cron自定义表达式 @Scheduled(cron = "${statistics.ams.day-cron}")private void test() { ...
- springboot 定时任务 Scheduled(fixedRate ,fixedDelay ,initialDelay,cron)使用
一.开启定时任务,加上注解 @EnableScheduling即可 @EnableScheduling @SpringBootApplication public class DemoApplicat ...
- SpringBoot 实战定时任务 Scheduled
序言 使用SpringBoot创建定时任务非常简单,目前主要有以下三种创建方式: 一.基于注解(@Scheduled) 二.基于接口(SchedulingConfigurer) 前者相信大家都很熟悉, ...
- @scheduled只执行一次_SpringBoot第四篇:定时任务@Scheduled
使用SpringBoot创建定时任务主要有三种创建方式: 1.基于注解(@Scheduled) 2.基于接口(SchedulingConfigurer)实际使用中我们往往想从数据库中读取指定时间来动态 ...
- springboot定时任务
使用SpringBoot创建定时任务非常简单,目前主要有以下三种创建方式: 一.基于注解(@Scheduled) 二.基于接口(SchedulingConfigurer) 前者相信大家都很熟悉,但是实 ...
- SpringBoot定时任务实现的两种方式介绍
今天给大家介绍SpringBoot定时任务实现的几种方式,希望对大家能有所帮助! 1.SpringTask 用法 框架介绍:SpringTask是Spring自带的轻量级定时任务工具,相比于Quart ...
最新文章
- Spring boot的Thymeleaf使用
- what is IOC
- java读取安卓本地文件_Java Android 二进制文件读写
- JSON数据格式以及与后台交互数据转换实例
- Receiver type ‘X’ for instance message is a forward declaration
- python twisted教程 二:缓慢的诗
- 坐标轨迹计算_工业机器人工具坐标系和用户坐标系的区别与联系
- 2021年最新UI/UE设计学习路线图
- numpy的array和matrix
- Foundation框架: 6.NSString的创建和导出
- Qt之QTableView的简单使用(含源码+注释)
- 有哪些比较好用的开源项目管理工具?
- /usr/local/bin/zsh没有文件或目录问题
- 极致体验,解密微信背后的音视频通话技术
- LevelDB整体介绍
- Safari无痕浏览影响localStorage
- php webmail,10个基于Ajax的PHP Webmail客户端
- 用函数求斐波那契数列前n项和
- renderdoc的使用
- Window对象简介
热门文章
- 弘辽科技:淘宝造物神榜如何选品?有哪些选品标准?
- 如果没有鼠标全用键盘操作电脑
- 微软产品 .NET 6 迁移之旅
- 操作系统习题知识点总结
- 网页性能提升之WebP
- 【spring-boot】spring-boot通过浏览器发送json格式数据,controler的处理
- html教程:关于网页字体的设置
- 操作系统内存管理,你能回答这8个问题吗?
- 两张图让你了解,Web前端开发就业前景及薪资究竟如何!
- IndexError: boolean index did not match indexed array along dimension 0; dimension is 82 but corresp