Spring Boot 定时任务单线程和多线程

Spring Boot 的定时任务:

第一种:把参数配置到.properties文件中:

代码:


  1. package com.accord.task;
  2. import java.text.SimpleDateFormat;
  3. import java.util.Date;
  4. import org.springframework.scheduling.annotation.Scheduled;
  5. import org.springframework.stereotype.Component;
  6. /**
  7. * 从配置文件加载任务信息
  8. * @author 王久印
  9. * 2018年3月1日
  10. */
  11. @Component
  12. public class ScheduledTask {
  13. private static final SimpleDateFormat dateFormat = new SimpleDateFormat("HH:mm:ss");
  14. //@Scheduled(fixedDelayString = "${jobs.fixedDelay}")
  15. @Scheduled(fixedDelayString = "2000")
  16. public void getTask1() {
  17. System.out.println("任务1,从配置文件加载任务信息,当前时间:" + dateFormat.format(new Date()));
  18. }
  19. @Scheduled(cron = "${jobs.cron}")
  20. public void getTask2() {
  21. System.out.println("任务2,从配置文件加载任务信息,当前时间:" + dateFormat.format(new Date()));
  22. }
  23. }

application.properties文件:


  1. jobs.fixedDelay=5000
  2. jobs.cron=0/5 * * * * ?

SpringBootCron2Application.java中:


  1. package com.accord;
  2. import org.springframework.boot.SpringApplication;
  3. import org.springframework.boot.autoconfigure.SpringBootApplication;
  4. import org.springframework.scheduling.annotation.EnableScheduling;
  5. @SpringBootApplication
  6. @EnableScheduling
  7. public class SpringBootCron2Application {
  8. public static void main(String[] args) {
  9. SpringApplication.run(SpringBootCron2Application.class, args);
  10. }
  11. }

注:@EnableScheduling  这个一定要加上;否则,不会定时启动任务!

@Scheduled中的参数说明:


  1. @Scheduled(fixedRate=2000):上一次开始执行时间点后2秒再次执行;
  2. @Scheduled(fixedDelay=2000):上一次执行完毕时间点后2秒再次执行;
  3. @Scheduled(initialDelay=1000, fixedDelay=2000):第一次延迟1秒执行,然后在上一次执行完毕时间点后2秒再次执行;
  4. @Scheduled(cron="* * * * * ?"):按cron规则执行。

在线Cron表达式生成器:http://cron.qqe2.com/

第二种定时任务:单线程和多线程

1、创建定时任务:


  1. package com.accord.task;
  2. import org.slf4j.Logger;
  3. import org.slf4j.LoggerFactory;
  4. import org.springframework.scheduling.annotation.Scheduled;
  5. import org.springframework.stereotype.Component;
  6. /**
  7. * 构建执行定时任务
  8. * @author 王久印
  9. * 2018年3月1日
  10. * TODO
  11. */
  12. @Component
  13. public class ScheduledTask2 {
  14. private Logger logger = LoggerFactory.getLogger(ScheduledTask2.class);
  15. private int fixedDelayCount = 1;
  16. private int fixedRateCount = 1;
  17. private int initialDelayCount = 1;
  18. private int cronCount = 1;
  19. @Scheduled(fixedDelay = 5000) //fixedDelay = 5000表示当前方法执行完毕5000ms后,Spring scheduling会再次调用该方法
  20. public void testFixDelay() {
  21. logger.info("===fixedDelay: 第{}次执行方法", fixedDelayCount++);
  22. }
  23. @Scheduled(fixedRate = 5000) //fixedRate = 5000表示当前方法开始执行5000ms后,Spring scheduling会再次调用该方法
  24. public void testFixedRate() {
  25. logger.info("===fixedRate: 第{}次执行方法", fixedRateCount++);
  26. }
  27. @Scheduled(initialDelay = 1000, fixedRate = 5000) //initialDelay = 1000表示延迟1000ms执行第一次任务
  28. public void testInitialDelay() {
  29. logger.info("===initialDelay: 第{}次执行方法", initialDelayCount++);
  30. }
  31. @Scheduled(cron = "0 0/1 * * * ?") //cron接受cron表达式,根据cron表达式确定定时规则
  32. public void testCron() {
  33. logger.info("===initialDelay: 第{}次执行方法", cronCount++);
  34. }
  35. }

使用 @Scheduled来创建定时任务 这个注解用来标注一个定时任务方法。

通过看 @Scheduled源码可以看出它支持多种参数:

(1)cron:cron表达式,指定任务在特定时间执行;

(2)fixedDelay:表示上一次任务执行完成后多久再次执行,参数类型为long,单位ms;

(3)fixedDelayString:与fixedDelay含义一样,只是参数类型变为String;

(4)fixedRate:表示按一定的频率执行任务,参数类型为long,单位ms;

(5)fixedRateString: 与fixedRate的含义一样,只是将参数类型变为String;

(6)initialDelay:表示延迟多久再第一次执行任务,参数类型为long,单位ms;

(7)initialDelayString:与initialDelay的含义一样,只是将参数类型变为String;

(8)zone:时区,默认为当前时区,一般没有用到。

2、开启定时任务:


  1. package com.accord;
  2. import org.springframework.boot.SpringApplication;
  3. import org.springframework.boot.autoconfigure.SpringBootApplication;
  4. import org.springframework.scheduling.annotation.EnableScheduling;
  5. @SpringBootApplication
  6. @EnableScheduling
  7. public class SpringBootCron2Application {
  8. public static void main(String[] args) {
  9. SpringApplication.run(SpringBootCron2Application.class, args);
  10. }
  11. }

注:这里的 @EnableScheduling  注解,它的作用是发现注解 @Scheduled的任务并由后台执行。没有它的话将无法执行定时任务。

引用官方文档原文:

@EnableScheduling ensures that a background task executor is created. Without it, nothing gets scheduled.

3、执行结果(单线程)

就完成了一个简单的定时任务模型,下面执行springBoot观察执行结果:

从控制台输入的结果中我们可以看出所有的定时任务都是在同一个线程池用同一个线程来处理的,那么我们如何来并发的处理各定时任务呢,请继续向下看。

4、多线程处理定时任务:

看到控制台输出的结果,所有的定时任务都是通过一个线程来处理的,我估计是在定时任务的配置中设定了一个SingleThreadScheduledExecutor,于是我看了源码,从ScheduledAnnotationBeanPostProcessor类开始一路找下去。果然,在ScheduledTaskRegistrar(定时任务注册类)中的ScheduleTasks中又这样一段判断:


  1. if (this.taskScheduler == null) {
  2. this.localExecutor = Executors.newSingleThreadScheduledExecutor();
  3. this.taskScheduler = new ConcurrentTaskScheduler(this.localExecutor);
  4. }

这就说明如果taskScheduler为空,那么就给定时任务做了一个单线程的线程池,正好在这个类中还有一个设置taskScheduler的方法:


  1. public void setScheduler(Object scheduler) {
  2. Assert.notNull(scheduler, "Scheduler object must not be null");
  3. if (scheduler instanceof TaskScheduler) {
  4. this.taskScheduler = (TaskScheduler) scheduler;
  5. }
  6. else if (scheduler instanceof ScheduledExecutorService) {
  7. this.taskScheduler = new ConcurrentTaskScheduler(((ScheduledExecutorService) scheduler));
  8. }
  9. else {
  10. throw new IllegalArgumentException("Unsupported scheduler type: " + scheduler.getClass());
  11. }
  12. }

这样问题就很简单了,我们只需用调用这个方法显式的设置一个ScheduledExecutorService就可以达到并发的效果了。我们要做的仅仅是实现SchedulingConfigurer接口,重写configureTasks方法就OK了;


  1. package com.accord.task;
  2. import org.springframework.context.annotation.Configuration;
  3. import org.springframework.scheduling.annotation.SchedulingConfigurer;
  4. import org.springframework.scheduling.config.ScheduledTaskRegistrar;
  5. import java.util.concurrent.Executors;
  6. /**
  7. * 多线程执行定时任务
  8. * @author 王久印
  9. * 2018年3月1日
  10. */
  11. @Configuration
  12. //所有的定时任务都放在一个线程池中,定时任务启动时使用不同都线程。
  13. public class ScheduleConfig implements SchedulingConfigurer {
  14. @Override
  15. public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {
  16. //设定一个长度10的定时任务线程池
  17. taskRegistrar.setScheduler(Executors.newScheduledThreadPool(10));
  18. }
  19. }

5、执行结果(并发)

通过控制台输出的结果看出每个定时任务都是在通过不同的线程来处理了。

原文地址:https://www.cnblogs.com/jpfss/p/10836851.html

时间: 2024-10-17 08:02:10

Spring Boot 定时任务单线程和多线程的相关文章

Spring Boot定时任务运行一段时间后自动关闭的解决办法

用Spring Boot默认支持的 Scheduler来运行定时任务,有时在服务器运行一段时间后会自动关闭.原因:Schedule默认是单线程运行定时任务的,即使是多个不同的定时任务,默认也是单线程运行.当线程挂掉时,定时任务也随之终止. 解决方法: 一.改为多线程执行定时任务: 加一个配置类,实现SchedulingConfigurer接口,重写configureTasks方法即可: import org.springframework.context.annotation.Configura

Spring Boot定时任务的使用

Spring Boot中配置定时任务极其简单...... import org.springframework.context.annotation.Configuration; import org.springframework.scheduling.annotation.EnableScheduling; import org.springframework.scheduling.annotation.Scheduled; import java.text.SimpleDateFormat

spring boot.定时任务问题记录(TaskScheduler/ScheduledExecutorService异常)

一.背景 spring boot的定时任务非常简单,只需要在启动类中加上@EnableScheduling注解,然后在对应的方法上配置@Scheduled就可以了,系统会自动处理并按照Scheduled中的配置定时执行方法. 但是在启动项目的时候,发生了很诡异的现象,有两个TaskScheduler/ScheduledExecutorService的异常打印了出来.但是系统并没有受影响,依然正常启动,而且定时任务也是正常执行. 2018-09-29 15:54:05,187 DEBUG main

spring boot 定时任务基于zookeeper的分布式锁实现

基于ZooKeeper分布式锁的流程 在zookeeper指定节点(locks)下创建临时顺序节点node_n 获取locks下所有子节点children 对子节点按节点自增序号从小到大排序 判断本节点是不是第一个子节点,若是,则获取锁:若不是,则监听比该节点小的那个节点的删除事件 若监听事件生效,则回到第二步重新进行判断,直到获取到锁 具体实现 添加Maven依赖: <?xml version="1.0" encoding="UTF-8"?> <

Spring Boot 定时任务 @Scheduled

项目开发中经常需要执行一些定时任务,比如在每天凌晨,需要从 implala 数据库拉取产品功能活跃数据,分析处理后存入到 MySQL 数据库中.类似这样的需求还有许多,那么怎么去实现定时任务呢,有以下几种实现方式. Java 定时任务的几种实现方式 基于 java.util.Timer 定时器,实现类似闹钟的定时任务 使用 Quartz.elastic-job.xxl-job 等开源第三方定时任务框架,适合分布式项目应用 使用 Spring 提供的一个注解: @Schedule,开发简单,使用比

SpringBoot系列:Spring Boot定时任务Spring Schedule

Spring Schedule是Spring提供的定时任务框架,相较于Quartz,Schedule更加简单易用,在中小型应用中,对于大部分需求,Schedule都可以胜任. 一.Spring Schedule使用演示 在 SpringBoot使用Spring Schedule非常简单,因为SpringBoot自身的starter中已经集成了Schedule,而不需要我们做更多的处理. 使用@EnableScheduling注解开启定时功能,该注解可以使用在启动类上,也可以注解于定时任务的类上.

spring boot 定时任务

package com.ict.conf; import org.springframework.context.annotation.Configuration; import org.springframework.scheduling.annotation.EnableScheduling; import org.springframework.scheduling.annotation.Scheduled; @Configuration @EnableScheduling // 启用定时

spring boot定时任务

1  在启动类上添加:@EnableScheduling // 开启定时任务 2  实现调度器 import java.util.Date; import org.apache.commons.lang3.StringUtils; import org.springframework.scheduling.Trigger; import org.springframework.scheduling.TriggerContext; import org.springframework.schedu

Spring Boot 定时+多线程执行

Spring Boot 定时任务有多种实现方式,我在一个微型项目中通过注解方式执行定时任务. 具体执行的任务,通过多线程方式执行,单线程执行需要1小时的任务,多线程下5分钟就完成了. 执行效率提升10倍以上,执行效率提升10倍以上,执行效率提升10倍以上. 重要的事情说三遍! 本文不深入介绍具体的原理,大家如果要实现类似的功能,只需要执行下面1~5即可. 至于为什么是上图,而不直接贴代码.直接上代码排版不齐,需要的可以留邮箱,我发给你. (1)定时任务实现 在需要定时执行的的方法上面增加注解 @