您好,登录后才能下订单哦!
这篇文章将为大家详细讲解有关SpringBoot定时任务如何在Java中使用,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文章后对相关知识有一定的了解。
一、SpringBoot使用Schedule
核心代码:
@Component
public class ScheduleTask {
private Logger logger = LoggerFactory.getLogger(ScheduleTask.class);
@Scheduled(cron = "0/1 * * * * ? ")
public void one() {
logger.info("one:" + new Date());
}
@Scheduled(cron = "0/1 * * * * ? ")
public void two() {
logger.info("two:" + new Date());
}
@Scheduled(cron = "0/1 * * * * ? ")
public void three() {
logger.info("three:" + new Date());
}
}运行效果如下:

除此之外还可以这样实现,核心代码:
@PropertySource(value = {
"classpath:task.properties",
}, encoding = "utf-8")
@Component("scheduleTask")
public class ScheduleTask implements SchedulingConfigurer {
@Value("${TEST_JOB_TASK_CRON}")
private String cron;
@Override
public void configureTasks(ScheduledTaskRegistrar scheduledTaskRegistrar) {
scheduledTaskRegistrar.addTriggerTask(new Runnable() {
@Override
public void run() {
System.out.println("执行任务:" + DateUtil.date());
}
}, new Trigger() {
@Override
public Date nextExecutionTime(TriggerContext triggerContext) {
return new CronTrigger(cron).nextExecutionTime(triggerContext);
}
});
}
public void setCron(String cron) {
this.cron = cron;
}
}有朋友或许很疑惑,为什么要写这么一大堆,这个与前面的代码又有何区别呢?
区别是多线程并行。其实多线程并行也可以不用这么写,只需写一段核心配置类代码即可。
定时任务多线程配置类:
@Configuration
public class ScheduleConfig implements SchedulingConfigurer {
public void configureTasks(ScheduledTaskRegistrar scheduledTaskRegistrar) {
scheduledTaskRegistrar.setScheduler(Executors.newScheduledThreadPool(5));
}
}再次启动,查看效果,如下:

由此看出走不同的线程执行,不同的线程执行的好处是,如果某一个线程挂掉后,并不会阻塞导致其它定时任务无法执行。
另外如果要想并发执行,前面的配置可以不要,直接用SpringBoot提供的现成注解即可,核心代码如下:
@Component
@EnableAsync
public class ScheduleAsyncTask {
private Logger logger = LoggerFactory.getLogger(ScheduleAsyncTask.class);
@Scheduled(cron = "0/1 * * * * ? ")
@Async
public void one() {
logger.info("one Async:" + new Date());
}
@Scheduled(cron = "0/1 * * * * ? ")
@Async
public void two() {
logger.info("two Async:" + new Date());
}
@Scheduled(cron = "0/1 * * * * ? ")
@Async
public void three() {
logger.info("three Async:" + new Date());
}
}除此外,还有基于schedule动态定时任务(所谓动态只不过是指cron表达式放在对应的数据表里),简单示例代码:
@Configuration
public class DynamicScheduleTask implements SchedulingConfigurer {
@Autowired
@SuppressWarnings("all")
CronMapper cronMapper;
@Mapper
public interface CronMapper {
@Select("select cron from cron limit 1")
public String getCron();
}
/**
* 执行定时任务.
*/
public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {
taskRegistrar.addTriggerTask(
//1.添加任务内容(Runnable)
() -> System.out.println("执行动态定时任务: " + LocalDateTime.now().toLocalTime()),
//2.设置执行周期(Trigger)
triggerContext -> {
//2.1 从数据库获取执行周期
String cron = cronMapper.getCron();
//2.2 合法性校验.
if (StringUtils.isEmpty(cron)) {
// Omitted Code ..
}
//2.3 返回执行周期(Date)
return new CronTrigger(cron).nextExecutionTime(triggerContext);
}
);
}
}核心配置文件(application.yml):
spring: datasource: url: jdbc:mysql://127.0.0.1:3306/test username: root password: 1234
SQL脚本:
DROP DATABASE IF EXISTS `test`;
CREATE DATABASE `test`;
USE `test`;
DROP TABLE IF EXISTS `cron`;
CREATE TABLE `cron` (
`cron_id` varchar(30) NOT NULL PRIMARY KEY,
`cron` varchar(30) NOT NULL
);
INSERT INTO `cron` VALUES ('1', '0/5 * * * * ?');运行效果如下:

<!--引入quartz定时框架--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-quartz</artifactId> </dependency>
spring: quartz: #相关属性配置 properties: org: quartz: scheduler: instanceName: clusteredScheduler instanceId: AUTO jobStore: class: org.quartz.impl.jdbcjobstore.JobStoreTX driverDelegateClass: org.quartz.impl.jdbcjobstore.StdJDBCDelegate tablePrefix: QRTZ_ isClustered: true clusterCheckinInterval: 10000 useProperties: false threadPool: class: org.quartz.simpl.SimpleThreadPool threadCount: 10 threadPriority: 5 threadsInheritContextClassLoaderOfInitializingThread: true #数据库方式 job-store-type: jdbc #初始化表结构 jdbc: initialize-schema: always datasource: url: jdbc:mysql://127.0.0.1:3306/test username: root password: 1234
@SpringBootApplication
@EnableScheduling
public class BlogQuartzApplication {
public static void main(String[] args) {
SpringApplication.run(BlogQuartzApplication.class, args);
}
}@Configuration
public class QuartzConfiguration {
// 使用jobDetail包装job
@Bean
public JobDetail myCronJobDetail() {
return JobBuilder.newJob(CouponTimeOutJob.class).withIdentity("couponTimeOutJob").storeDurably().build();
}
// 把jobDetail注册到Cron表达式的trigger上去
@Bean
public Trigger CronJobTrigger() {
CronScheduleBuilder cronScheduleBuilder = CronScheduleBuilder.cronSchedule("0/1 * * * * ?");
return TriggerBuilder.newTrigger()
.forJob(myCronJobDetail())
.withIdentity("CouponTimeOutJobTrigger")
.withSchedule(cronScheduleBuilder)
.build();
}
}public class CouponTimeOutJob extends QuartzJobBean {
@Override
protected void executeInternal(JobExecutionContext jobExecutionContext) throws JobExecutionException {
System.out.println("定时任务执行");
}
}(1)对应的数据库会生成定时任务相关的数据表

(2)控制台不断输出定时任务执行日志

之前写过一样的例子,如今简化了下。
关于xxl-job使用详情,可以参考我的这篇文章:
SpringBoot整合Xxl-Job
<dependency> <groupId>com.xuxueli</groupId> <artifactId>xxl-job-core</artifactId> <version>2.2.0</version> </dependency>
@Configuration
public class XxlJobConfig {
private Logger logger = LoggerFactory.getLogger(XxlJobConfig.class);
@Value("${xxl.job.admin.addresses}")
private String adminAddresses;
@Value("${xxl.job.executor.appname}")
private String appName;
@Value("${xxl.job.executor.ip}")
private String ip;
@Value("${xxl.job.executor.port}")
private int port;
@Value("${xxl.job.accessToken}")
private String accessToken;
@Value("${xxl.job.executor.logpath}")
private String logPath;
@Value("${xxl.job.executor.logretentiondays}")
private int logRetentionDays;
@Bean(initMethod = "start", destroyMethod = "destroy")
public XxlJobSpringExecutor xxlJobExecutor() {
logger.info(">>>>>>>>>>> xxl-job config init.");
XxlJobSpringExecutor xxlJobSpringExecutor = new XxlJobSpringExecutor();
xxlJobSpringExecutor.setAdminAddresses(adminAddresses);
xxlJobSpringExecutor.setAppname(appName);
xxlJobSpringExecutor.setIp(ip);
xxlJobSpringExecutor.setPort(port);
xxlJobSpringExecutor.setAccessToken(accessToken);
xxlJobSpringExecutor.setLogPath(logPath);
xxlJobSpringExecutor.setLogRetentionDays(logRetentionDays);
return xxlJobSpringExecutor;
}
}# web port server.port=8081 # no web #spring.main.web-environment=false ### xxl-job admin address list, such as "http://address" or "http://address01,http://address02" xxl.job.admin.addresses=http://127.0.0.1:8080/xxl-job-admin ### xxl-job, access token xxl.job.accessToken= ### xxl-job executor appname xxl.job.executor.appname=blog-job-xxl-job ### xxl-job executor registry-address: default use address to registry , otherwise use ip:port if address is null xxl.job.executor.address= ### xxl-job executor server-info xxl.job.executor.ip= xxl.job.executor.port=8888 ### xxl-job executor log-path xxl.job.executor.logpath=/data/applogs/xxl-job/jobhandler ### xxl-job executor log-retention-days xxl.job.executor.logretentiondays=30
@Component
public class XxlJobTaskExample {
@XxlJob("blogJobHandler")
public ReturnT<String> blogJobHandler(String param) throws Exception {
System.out.println("执行");
XxlJobLogger.log("XXL-JOB, Hello World.");
for (int i = 0; i < 5; i++) {
XxlJobLogger.log("beat at:" + i);
TimeUnit.SECONDS.sleep(2);
}
return ReturnT.SUCCESS;
}
}分别如下所示:


<!-- 分布式定时任务锁 --> <!-- https://mvnrepository.com/artifact/net.javacrumbs.shedlock/shedlock-spring --> <dependency> <groupId>net.javacrumbs.shedlock</groupId> <artifactId>shedlock-spring</artifactId> <version>4.0.4</version> </dependency> <!-- 使用redis做分布式任务 --> <dependency> <groupId>net.javacrumbs.shedlock</groupId> <artifactId>shedlock-provider-redis-spring</artifactId> <version>2.5.0</version> </dependency> <!-- redis组件 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency>
@Configuration
@EnableSchedulerLock(defaultLockAtMostFor = "PT30M")
public class ShedLockConfig {
@Bean
public LockProvider lockProvider(RedisTemplate redisTemplate) {
return new RedisLockProvider(redisTemplate.getConnectionFactory());
}
}@Component
public class TaskSchedule {
/**
* 每分钟执行一次
* [秒] [分] [小时] [日] [月] [周] [年]
*/
@Scheduled(cron = "1 * * * * ?")
@SchedulerLock(name = "synchronousSchedule")
public void SynchronousSchedule() {
System.out.println("Start run schedule to synchronous data:" + new Date());
}
}@SpringBootApplication
@EnableScheduling
public class ShedLockRedisApplication {
public static void main(String[] args) {
SpringApplication.run(ShedLockRedisApplication.class);
}
}server: tomcat: uri-encoding: UTF-8 max-threads: 1000 min-spare-threads: 30 port: 8083 spring: redis: database: 0 host: localhost port: 6379 password: # 密码(默认为空) timeout: 6000ms # 连接超时时长(毫秒) jedis: pool: max-active: 1000 # 连接池最大连接数(使用负值表示没有限制) max-wait: -1ms # 连接池最大阻塞等待时间(使用负值表示没有限制) max-idle: 10 # 连接池中的最大空闲连接 min-idle: 5 # 连接池中的最小空闲连接
我之所以用shedlock是因为确保在集群环境下各微服务的定时任务只执行一个,而不是全部都运行相同的定时任务。
本次测试效果如下:

关于SpringBoot定时任务如何在Java中使用就分享到这里了,希望以上内容可以对大家有一定的帮助,可以学到更多知识。如果觉得文章不错,可以把它分享出去让更多的人看到。
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。