SpirngBoot - 定时任务入门(@Scheduled )
程序员文章站
2022-05-20 14:11:02
...
项目开发中经常需要执行一些定时任务,比如需要在每天凌晨时候,分析一次前一天的日志信息。Spring为我们提供了异步执行任务调度的方式,提供TaskExecutor 、TaskScheduler 接口。
SpringBoot中使用两个注解:@EnableScheduling、@Scheduled来简单实现定时任务。
【1】@Scheduled注解
按照惯例,先看源码:
/**
* An annotation that marks a method to be scheduled. Exactly one of
* the {@link #cron()}, {@link #fixedDelay()}, or {@link #fixedRate()}
* attributes must be specified.
*// 使一个方法定时被执行的注解。其属性cron/fixedDelay/fixedRate必须有一个被指定
* <p>The annotated method must expect no arguments. It will typically have
* a {@code void} return type; if not, the returned value will be ignored
* when called through the scheduler.
*//该注解标记的方法没有参数,也没有返回值。即使写了返回值,也会被忽略。
* <p>Processing of {@code @Scheduled} annotations is performed by
* registering a {@link ScheduledAnnotationBeanPostProcessor}.
* 该注解被ScheduledAnnotationBeanPostProcessor处理器解析。
*
* This can be done manually or, more conveniently, through the {@code <task:annotation-driven/>}
* element or @{@link EnableScheduling} annotation.
*可以手动注册该bean,当然更方便的是使用<task:annotation-driven/>配置或者@EnableScheduling注解。
* <p>This annotation may be used as a <em>meta-annotation</em> to create custom
* <em>composed annotations</em> with attribute overrides.
*
* @see EnableScheduling
* @see ScheduledAnnotationBeanPostProcessor
* @see Schedules
*/
@Target({ElementType.METHOD, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Repeatable(Schedules.class)
public @interface Scheduled {
/**
* A cron-like expression, extending the usual UN*X definition to include
* triggers on the second as well as minute, hour, day of month, month
* and day of week. e.g. {@code "0 * * * * MON-FRI"} means once per minute on
* weekdays (at the top of the minute - the 0th second).
* @return an expression that can be parsed to a cron schedule
* @see org.springframework.scheduling.support.CronSequenceGenerator
*/
cron表达式
String cron() default "";
/**
* A time zone for which the cron expression will be resolved. By default, this
* attribute is the empty String (i.e. the server's local time zone will be used).
* @return a zone id accepted by {@link java.util.TimeZone#getTimeZone(String)},
* or an empty String to indicate the server's default time zone
* @since 4.0
* @see org.springframework.scheduling.support.CronTrigger#CronTrigger(String, java.util.TimeZone)
* @see java.util.TimeZone
*/
String zone() default "";
/**
* Execute the annotated method with a fixed period in milliseconds between the
* end of the last invocation and the start of the next.
* @return the delay in milliseconds
*/
周期为在最后一次调用结束和下一次调用开始,以毫秒为单位,
固定周期地执行注释的方法。
long fixedDelay() default -1;
/**
* Execute the annotated method with a fixed period in milliseconds between the
* end of the last invocation and the start of the next.
* @return the delay in milliseconds as a String value, e.g. a placeholder
*/
周期间隔为在最后一次调用结束和下一次调用开始,以毫秒为单位,
固定周期地执行注释的方法。
String fixedDelayString() default "";
/**
* Execute the annotated method with a fixed period in milliseconds between
* invocations.
* @return the period in milliseconds
*/
固定周期地执行注解方法,周期为调用间隔,单位为毫秒
long fixedRate() default -1;
/**
* Execute the annotated method with a fixed period in milliseconds between
* invocations.
* @return the period in milliseconds as a String value, e.g. a placeholder
*/
String fixedRateString() default "";
/**
* Number of milliseconds to delay before the first execution of a
* {@link #fixedRate()} or {@link #fixedDelay()} task.
* @return the initial delay in milliseconds
* @since 3.2
*/
fixedRate() 或fixedDelay()第一次执行前延迟的毫秒数
long initialDelay() default -1;
/**
* Number of milliseconds to delay before the first execution of a
* {@link #fixedRate()} or {@link #fixedDelay()} task.
* @return the initial delay in milliseconds as a String value, e.g. a placeholder
* @since 3.2.2
*/
String initialDelayString() default "";
}
【2】@EnableScheduling 注解
/**
* Enables Spring's scheduled task execution capability, similar to
* functionality found in Spring's {@code <task:*>} XML namespace. To be used
* on @{@link Configuration} classes as follows:
*
* <pre class="code">
* @Configuration
* @EnableScheduling
* public class AppConfig {
*
* // various @Bean definitions
* }</pre>
*// 启动Spring的定时任务执行能力,通常用在配置类上面,类似于xml片段<task:*>。
* This enables detection of @{@link Scheduled} annotations on any Spring-managed
* bean in the container.
* //该注解会使Spring 容器中所有bean中的@Scheduled注解起作用。
*
* For example, given a class {@code MyTask}
*
* <pre class="code">
* package com.myco.tasks;
*
* public class MyTask {
*// 每1000ms 执行一次该方法
* @Scheduled(fixedRate=1000)
* public void work() {
* // task execution logic
* }
* }</pre>
*
* the following configuration would ensure that {@code MyTask.work()} is called
* once every 1000 ms:
* // 如下配置确保MyTask.work()每1000ms被调用一次。
* <pre class="code">
* @Configuration
* @EnableScheduling
* public class AppConfig {
*
* @Bean
* public MyTask task() {
* return new MyTask();
* }
* }</pre>
*
* Alternatively, if {@code MyTask} were annotated with {@code @Component}, the
* following configuration would ensure that its {@code @Scheduled} method is
* invoked at the desired interval:
*
* <pre class="code">
* @Configuration
* @EnableScheduling
* @ComponentScan(basePackages="com.myco.tasks")
* public class AppConfig {
* }</pre>
*
* Methods annotated with {@code @Scheduled} may even be declared directly within
* {@code @Configuration} classes:
*// 甚至可以直接在配置类中写@Scheduled注解标注的方法。
* <pre class="code">
* @Configuration
* @EnableScheduling
* public class AppConfig {
*
* @Scheduled(fixedRate=1000)
* public void work() {
* // task execution logic
* }
* }</pre>
*
* <p>By default, will be searching for an associated scheduler definition: either
* a unique {@link org.springframework.scheduling.TaskScheduler} bean in the context,
* or a {@code TaskScheduler} bean named "taskScheduler" otherwise; the same lookup
* will also be performed for a {@link java.util.concurrent.ScheduledExecutorService}
* bean.
* If neither of the two is resolvable, a local single-threaded default
* scheduler will be created and used within the registrar.
*// 如果上面两个定时任务处理器都没有被找到,一个本地单线程默认处理器将会被创建并被注册器使用。
* <p>When more control is desired, a {@code @Configuration} class may implement
* {@link SchedulingConfigurer}.
* // 如果想获得更多的控制,配置类应该实现SchedulingConfigurer接口。
*
* This allows access to the
* {@link ScheduledTaskRegistrar} instance.
* // 这将可以获取底层的ScheduledTaskRegistrar实例。
*
* For example, the following example
* demonstrates how to customize the {@link Executor} used to execute scheduled
* tasks:
*// 下面的例子演示了如何自定义Executor去执行定时任务。
* <pre class="code">
* @Configuration
* @EnableScheduling
* public class AppConfig implements SchedulingConfigurer {
*
* @Override
* public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {
* taskRegistrar.setScheduler(taskExecutor());
* }
*
* @Bean(destroyMethod="shutdown")
* public Executor taskExecutor() {
* return Executors.newScheduledThreadPool(100);
* }
* }</pre>
*
* <p>Note in the example above the use of {@code @Bean(destroyMethod="shutdown")}.
* // 注意上面例子中@Bean(destroyMethod="shutdown")的使用。
*
* This ensures that the task executor is properly shut down when the Spring
* application context itself is closed.
*// 这将确保线程任务执行器在Spring容器被销毁时正确的关闭。
* <p>Implementing {@code SchedulingConfigurer} also allows for fine-grained
* control over task registration via the {@code ScheduledTaskRegistrar}.
* // 实现SchedulingConfigurer还可以通过ScheduledTaskRegistrar对任务注册实细粒度的控制。
*
* For example, the following configures the execution of a particular bean
* method per a custom {@code Trigger} implementation:
*
* <pre class="code">
* @Configuration
* @EnableScheduling
* public class AppConfig implements SchedulingConfigurer {
*
* @Override
* public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {
* taskRegistrar.setScheduler(taskScheduler());
* taskRegistrar.addTriggerTask(
* new Runnable() {
* public void run() {
* myTask().work();
* }
* },
* new CustomTrigger()
* );
* }
*
* @Bean(destroyMethod="shutdown")
* public Executor taskScheduler() {
* return Executors.newScheduledThreadPool(42);
* }
*
* @Bean
* public MyTask myTask() {
* return new MyTask();
* }
* }</pre>
*
* <p>For reference, the example above can be compared to the following Spring XML
* configuration:
*
* <pre class="code">
* {@code
* <beans>
*
* <task:annotation-driven scheduler="taskScheduler"/>
*
* <task:scheduler id="taskScheduler" pool-size="42"/>
*
* <task:scheduled-tasks scheduler="taskScheduler">
* <task:scheduled ref="myTask" method="work" fixed-rate="1000"/>
* </task:scheduled-tasks>
*
* <bean id="myTask" class="com.foo.MyTask"/>
*
* </beans>
* }</pre>
*
* The examples are equivalent save that in XML a <em>fixed-rate</em> period is used
* instead of a custom <em>{@code Trigger}</em> implementation; this is because the
* {@code task:} namespace {@code scheduled} cannot easily expose such support. This is
* but one demonstration how the code-based approach allows for maximum configurability
* through direct access to actual componentry.<p>
*
* @see Scheduled
* @see SchedulingConfiguration
* @see SchedulingConfigurer
* @see ScheduledTaskRegistrar
* @see Trigger
* @see ScheduledAnnotationBeanPostProcessor
*/
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Import(SchedulingConfiguration.class)
@Documented
public @interface EnableScheduling {
}
【3】代码实例
Service如下(这里使用cron表达式):
@Service
public class ScheduledService {
// 每天的整分调用一次该方法
@Scheduled(cron = "0 * * * * 0-7")
public void hello(){
System.out.println("hello...");
}
}
在主程序上添加@EnableScheduling注解如下:
@SpringBootApplication
@EnableScheduling
public class SpringBoot01CacheApplication {
public static void main(String[] args) {
SpringApplication.run(SpringBoot01CacheApplication.class, args);
}
}
fixedRate ,fixedDelay 和initialDelay
代码示例如下:
//上一次 项目启动时间点之后 5 秒执行一次
@Scheduled(fixedRate = 5000)
public void fixedRate(){
System.out.println("fixedRate: " + new SimpleDateFormat("HH:mm:ss").format(new Date()));
}
//上一次 结束时间点之后 每50秒执行一次
@Scheduled(fixedDelay = 50000)
public void fixedDelay(){
for (int i = 0; i < 10; i++){
System.out.println("fixedDelay" + i + new SimpleDateFormat("HH:mm:ss").format(new Date()));
}
}
// initialDelay :fixedRate() 或fixedDelay()第一次执行前延迟的毫秒数
//第一次延迟50秒执行,之后按照fixedRate的规则每6秒执行一次
@Scheduled(initialDelay = 50000,fixedRate = 6000)
public void initialDelayFixedRate (){
for (int i = 0; i < 10; i++){
System.out.println("initialDelayFixedRate :" + i + new SimpleDateFormat("HH:mm:ss").format(new Date()) );
}
}
【4】cron表达式
cron表达式属性如下:
second(秒), minute(分), hour(时),day of month(日),month(月),day of week(周几)
字段与值表格如下:
字段 | 允许值 | 允许的特殊符号 |
---|---|---|
秒 | 0-59 | ,-*/ |
分 | 0-59 | ,-*/ |
小时 | 0-23 | ,-*/ |
日期 | 1-31 | ,-*?/LWC |
月份 | 1-12 | ,-*/ |
星期 | 0-7或SUN-SAT 0 7是SUN | ,-*?/LC# |
特殊符号释义如下:
特殊符号 | 代表含义 |
---|---|
, | 枚举 |
- | 区间 |
* | 任意 |
/ | 步长 |
? | 日/星期冲突匹配 |
L | 最后 |
W | 工作日 |
C | 和Calendar联系后计算过的值 |
# | 星期 4#2 第2个星期四 |
示例如下:
0 0/15 14,18 * * ? -- 每天14点整和18点整,每隔5分钟执行一次
0 15 10 ? * 1-6 -- 每个月的周一到周六 10:15分执行一次
0 0 2 ? * 6L -- 每个月的最后一个周六凌晨2点执行一次
0 0 2 LW * ? -- 每个月的最后一个工作日凌晨2点执行一次
0 0 2-4 ? * 1#1 -- 每个月的第一个周一凌晨2点到4点期间,每个整点都执行一次
实现定时任务的方式很多,其他的有JDK 自带的 TimerTask or Timer、使用开源作业调度框架 Quartz、线程池 ScheduleExecutorService 和其实现类ScheduledThreadPoolExecutor。
参考博文:多线程并发之Executor。
上一篇: InfluxDB 介绍、安装及基本使用
下一篇: Whois 的PHP代码_PHP