Java小强个人技术博客站点    手机版
当前位置: 首页 >> 框架 >> SpringBoot实现定时任务

SpringBoot实现定时任务

40791 框架 | 2021-3-22

这里主要介绍使用Spring Task,Spring3.0以后自带的task,可以将它看成一个轻量级的Quartz,而且使用起来比Quartz简单许多。

首先在POM中导入依赖:

<dependencies>
  <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
  </dependency>
  <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter</artifactId>
  </dependency>
  <dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <optional>true</optional>
  </dependency>
  <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-test</artifactId>
    <scope>test</scope>
  </dependency>
</dependencies>


创建任务执行类:

package com.example.demo.task;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import com.example.demo.util.DateUtil;

@Component
public class ScheduledService {
	
	private final Logger log = LoggerFactory.getLogger(this.getClass());
	
	@Scheduled(cron = "0/5 * * * * *")
    public void scheduled(){
        log.info("使用cron执行:{}", DateUtil.getDateCurrent());
    }
	
	// 它的间隔时间是根据上次的任务结束的时候开始计时的。
	// 比如一个方法上设置了fixedDelay=5*1000,那么当该方法某一次执行结束后,开始计算时间,当时间达到5秒,就开始再次执行该方法。
	// 加上注解@EnableAsync(类上)和@Async(方法上),加了注解以后,就开启了多线程模式,
	// 当到了下一次任务的执行时机时,如果上一次任务还没执行完,就会自动创建一个新的线程来执行它。
	// 异步执行也可以理解为保证了任务以固定速度执行。
    @Scheduled(fixedRate = 600*1000)
    public void scheduled1() {
        log.info("使用fixedRate执行:{}", DateUtil.getDateCurrent());
    }
    
    // 它的间隔时间是根据上次任务开始的时候计时的。
    // 比如当方法上设置了fiexdRate=5*1000,该执行该方法所花的时间是2秒,那么3秒后就会再次执行该方法。
    @Scheduled(fixedDelay = 5000)
    public void scheduled2() {
        log.info("使用fixedDelay执行:{}", DateUtil.getDateCurrent());
    }

}


主要就是看@Scheduled注解,这三种方式的意思已经写在了注释上,更为细节的解释可以自行百度。

然后是启动类

package com.example.demo;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.scheduling.annotation.EnableScheduling;

@SpringBootApplication
@EnableScheduling
public class DemoApplication {

	public static void main(String[] args) {
		SpringApplication.run(DemoApplication.class, args);
	}

}

这里增加了一个@EnableScheduling的注解在类上,否则不会启动Task。

我们看打印的日志

2021-03-22 11:14:34.653  INFO 7420 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat started on port(s): 8080 (http) with context path ''
2021-03-22 11:14:34.679  INFO 7420 --- [   scheduling-1] com.example.demo.task.ScheduledService   : 使用fixedRate执行:2021-03-22 11:14:34
2021-03-22 11:14:34.679  INFO 7420 --- [   scheduling-1] com.example.demo.task.ScheduledService   : 使用fixedDelay执行:2021-03-22 11:14:34
2021-03-22 11:14:34.682  INFO 7420 --- [           main] com.example.demo.DemoApplication         : Started DemoApplication in 3.958 seconds (JVM running for 4.42)
2021-03-22 11:14:35.001  INFO 7420 --- [   scheduling-1] com.example.demo.task.ScheduledService   : 使用cron执行:2021-03-22 11:14:35
2021-03-22 11:14:39.680  INFO 7420 --- [   scheduling-1] com.example.demo.task.ScheduledService   : 使用fixedDelay执行:2021-03-22 11:14:39
2021-03-22 11:14:40.003  INFO 7420 --- [   scheduling-1] com.example.demo.task.ScheduledService   : 使用cron执行:2021-03-22 11:14:40
2021-03-22 11:14:44.682  INFO 7420 --- [   scheduling-1] com.example.demo.task.ScheduledService   : 使用fixedDelay执行:2021-03-22 11:14:44
2021-03-22 11:14:45.000  INFO 7420 --- [   scheduling-1] com.example.demo.task.ScheduledService   : 使用cron执行:2021-03-22 11:14:45
2021-03-22 11:14:49.683  INFO 7420 --- [   scheduling-1] com.example.demo.task.ScheduledService   : 使用fixedDelay执行:2021-03-22 11:14:49
2021-03-22 11:14:50.013  INFO 7420 --- [   scheduling-1] com.example.demo.task.ScheduledService   : 使用cron执行:2021-03-22 11:14:50

我们看到三个方法使同一个线程中串行执行,如果只有一个定时任务,这样做肯定没问题,当定时任务增多,如果一个任务卡死,会导致其他任务也无法执行。

在传统的Spring项目中,我们可以在xml配置文件添加task的配置,而在SpringBoot项目中一般使用config配置类的方式添加配置,所以新建一个AsyncConfig类。

package com.example.demo.task;

import java.util.concurrent.Executor;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;

@Configuration
@EnableAsync
public class AsyncConfig {
	
	private int corePoolSize = 5;
	private int maxPoolSize = 10;
	private int queueCapacity = 10;

	@Bean
	public Executor taskExecutor() {
		ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
		executor.setCorePoolSize(corePoolSize);
		executor.setMaxPoolSize(maxPoolSize);
		executor.setQueueCapacity(queueCapacity);
		executor.initialize();
		return executor;
	}
}


@Configuration:表明该类是一个配置类

@EnableAsync:开启异步事件的支持

然后在定时任务的类或者方法上添加@Async 。最后重启项目,每一个任务都是在不同的线程中。

2021-03-22 11:16:52.823  INFO 9708 --- [           main] com.example.demo.DemoApplication         : Started DemoApplication in 3.888 seconds (JVM running for 4.346)
2021-03-22 11:16:52.832  INFO 9708 --- [ taskExecutor-1] com.example.demo.task.ScheduledService   : 使用fixedRate执行:2021-03-22 11:16:52
2021-03-22 11:16:52.834  INFO 9708 --- [ taskExecutor-2] com.example.demo.task.ScheduledService   : 使用fixedDelay执行:2021-03-22 11:16:52
2021-03-22 11:16:55.002  INFO 9708 --- [ taskExecutor-3] com.example.demo.task.ScheduledService   : 使用cron执行:2021-03-22 11:16:55
2021-03-22 11:16:57.836  INFO 9708 --- [ taskExecutor-4] com.example.demo.task.ScheduledService   : 使用fixedDelay执行:2021-03-22 11:16:57
2021-03-22 11:17:00.003  INFO 9708 --- [ taskExecutor-5] com.example.demo.task.ScheduledService   : 使用cron执行:2021-03-22 11:17:00
2021-03-22 11:17:02.837  INFO 9708 --- [ taskExecutor-1] com.example.demo.task.ScheduledService   : 使用fixedDelay执行:2021-03-22 11:17:02


springboot.jpg

结束

推荐您阅读更多有关于“ spring Task Timer springboot cron ”的文章

上一篇:node.js安装及环境变量配置 下一篇:maven打war包时XML和properties配置文件丢失

猜你喜欢

发表评论:

评论:

回复 Java小强 评论于 2021-03-22 11:19
打印时有个获取时间的公用方法
/**
* 获取当前日期时间格式
* @return yyyy-MM-dd HH:mm:ss格式的时间
*/
public static String getDateCurrent(){
    return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date());
}