spring3.0版本之后自带定时任务,提供了@EnableScheduling注解和@Scheduled注解来实现定时任务功能。
今天咱们先分享一下,基于注解的姿势。
基于注解的的定时任务,其实使用起来比较简单,首先在任务类上添加 @EnableScheduling注解即可。
当然,也可以加载任务执行类上。
@EnableScheduling
@SpringBootApplication
public class TestApplication {
public static void main(String[] args) {
SpringApplication.run(TestApplication.class, args);
}
}
@Component
@EnableScheduling
public class TestTask {
@Scheduled(cron = "0/10 * * * * ?")
public void test1() {
System.out.println(Thread.currentThread().getName() + "have a test1");
}
@Scheduled(cron = "0/13 * * * * ?")
public void test2() {
System.out.println(Thread.currentThread().getName() + "have a test");
}
}
@Scheduled(cron = "0/10 * * * * ?")
public void test2() {
System.out.println(Thread.currentThread().getName() + "cronb");
}
如上,每10s执行一次。
2 基于fixedRate
@Scheduled(fixedRate = 1000 * 1)
public void test2() {
System.out.println(Thread.currentThread().getName() + " fixedRate");
}
这个属性是在上一个调用开始之后,再次调用的间隔时间,不需要等待上次调用结束,这样会导致存在重复执行的问题。
当然,如果在这个间隔时间内,比如1s内能执行完,也可以使用此方式。
3 基于fixedDelay
@Scheduled(fixedDelay = 1000 * 1)
public void test2() {
System.out.println(Thread.currentThread().getName() + "fixedDelay");
}
这个属性和fixedRate是反着的,这个意思是,拿上边的例子来讲的话,会在方法体中执行完成后的延迟ss开始执行。
注:对定时任务的增加@Component注解,交给spring容器去管理。
默认情况下,如果什么不进行配置,会存在一个问题,系统中所有的定时任务是都是使用一个线程去执行的,什么意思呢,假设同一个时刻有2个定时任务需要执行,那只可能有一个定时任务在执行,所以,若果解决这个问题,有两种解决方案。一个是定义任务调度线程池,另一个是自定义线程池,使用@Async异步执行的方式。
首先第一种方式:在配置类中 @configure 配置如下
/**
* 执行周期性或定时任务
*/
@Bean(name = "scheduledExecutorService")
protected ScheduledExecutorService scheduledExecutorService()
{
return new ScheduledThreadPoolExecutor(corePoolSize,
new BasicThreadFactory.Builder().namingPattern("schedule-pool-%d").daemon(true).build())
{
@Override
protected void afterExecute(Runnable r, Throwable t)
{
super.afterExecute(r, t);
Threads.printException(r, t);
}
};
}
或
@Bean
public TaskScheduler taskScheduler(){
ThreadPoolTaskScheduler executor = new ThreadPoolTaskScheduler();
executor.setPoolSize(10);
executor.setThreadNamePrefix("my task-");
return executor;
}
输出结果
my task-1---> test
my task-2---> test2
my task-1---> test
.还有一种,是通过框架自带的多线程,来处理。。 上代码。。
@Component
@EnableScheduling
@EnableAsync
public class TestTask {
@Async
@Scheduled(cron = "0/10 * * * * ?")
public void test1() {
System.out.println(Thread.currentThread().getName() + "TEST1");
}
@Scheduled(cron = "0/13 * * * * ?")
public void test2() {
System.out.println(Thread.currentThread().getName() + "TEST2");
}
}
执行结果如下:
my task-2TEST2
SimpleAsyncTaskExecutor-2TEST1
SimpleAsyncTaskExecutor-3TEST1
my task-3TEST2
my task-1TEST2
SimpleAsyncTaskExecutor-4TEST1
SimpleAsyncTaskExecutor-5TEST1
my task-3TEST2
SimpleAsyncTaskExecutor-6TEST1
说白了,就是在不停服务的情况下,修改执行的时间。
首先,在定时任务类商@EnabledScheduling 注解不可少,关键的实现SchedulingConfigurer接口。
其次,设置cron, 即 自动执行的时间点。
第三,动态获取cron,通过此处,在外边灵活修改执行时间
最后,设置任务触发器,触发任务执行。
直接上代码
package com.lianxin.web.controller.schedul;
import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.Trigger;
import org.springframework.scheduling.TriggerContext;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.scheduling.annotation.SchedulingConfigurer;
import org.springframework.scheduling.config.ScheduledTaskRegistrar;
import org.springframework.scheduling.support.CronTrigger;
import org.springframework.stereotype.Component;
import java.time.LocalDate;
import java.util.Date;
@Component
@EnableScheduling
@Slf4j
public class TaskCronChange implements SchedulingConfigurer {
public static String cron;
@Override
public void configureTasks(ScheduledTaskRegistrar scheduledTaskRegistrar) {
cron = "0/1 * * * * *"; // 项目启动时,会加载此配置
log.info("11111111111");
Runnable task = new Runnable() {
@Override
public void run() {
log.info("222222222222");
}
};
Trigger trigger = new Trigger(){
@Override
public Date nextExecutionTime(TriggerContext triggerContext) {
log.info("333333333333");
cron = "0/1 * * * * *";// TODO 此处获取最新的执行时间
CronTrigger cronTrigger = new CronTrigger(cron);
Date date = cronTrigger.nextExecutionTime(triggerContext);
log.info("44444444444");
return date;
}
};
scheduledTaskRegistrar.addTriggerTask(task,trigger);
}
}
要说明的是,更新执行时间,是每次在执行任务之后,再去更新执行时间,所以,当你修改一次执行时间之后,需要在执行完一次任务之后,才会更新这个执行时间,这样,下次的任务执行的时候,才会按照最新的任务执行时间去执行。
核心是使用ScheduledTaskRegistrar.addTriggerTask方法去更新任务的执行时间。
好,先说到这,下回分享 cron的用法
页面更新:2024-02-19
本站资料均由网友自行发布提供,仅用于学习交流。如有版权问题,请与我联系,QQ:4156828
© CopyRight 2020-2024 All Rights Reserved. Powered By 71396.com 闽ICP备11008920号-4
闽公网安备35020302034903号