Springboot定时任务@Scheduled详解

2 篇文章 0 订阅
2 篇文章 0 订阅

一、使用的注解: @Scheduled 和 @EnableScheduling

@EnableScheduling

package com.foreverchan.springboot;
 
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.scheduling.annotation.EnableScheduling;
 
/**
 * Spring Boot启动类
 *
 * @author ForeverChan
 * @date 2019/5/18 16:54
 */
@SpringBootApplication
@EnableScheduling
public class MyBootApplication {
    public static void main(String[] args) {
        SpringApplication.run(MyBootApplication .class, args);
    }
}

注解EnableScheduling也可以写在任务的执行类上

@Scheduled注解标识任务

package com.foreverchan.springboot.task;
 
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
 
/**
 * 通过@Scheduled创建任务
 * @author ForeverChan
 * @date 2019/5/18 16:54
 */
@Component
public class MyTestTask {
 	/**
 	 * 每隔一秒执行一次任务test01
 	 */
    @Scheduled(fixedDelay = 1000)
    public void test01() {
        System.out.println("my-test01 start");
        System.out.println("执行业务逻辑...");
        System.out.println("my-test01 end");
    }
 	/**
 	 * 每隔一秒执行一次任务test02
 	 */
    @Scheduled(fixedDelay = 1000)
    public void test02() {
        System.out.println("my-test02 start");
        try {
        	//睡1分钟
            Thread.sleep(60 * 1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("my-test02 end");
    }
}

除了使用fixedDelay还可以使用cron

这是一个时间表达式,可以通过简单的配置就能完成各种时间的配置,我们通过CRON表达式几乎可以完成任意的时间搭配,它包含了六或七个域:
Seconds : 可出现", - * /"四个字符,有效范围为0-59的整数
Minutes : 可出现", - * /"四个字符,有效范围为0-59的整数
Hours : 可出现", - * /"四个字符,有效范围为0-23的整数
DayofMonth : 可出现", - * / ? L W C"八个字符,有效范围为0-31的整数
Month : 可出现", - * /"四个字符,有效范围为1-12的整数或JAN-DEc
DayofWeek : 可出现", - * / ? L C #"四个字符,有效范围为1-7的整数或SUN-SAT两个范围。1表示星期天,2表示星期一, 依次类推
Year : 可出现", - * /"四个字符,有效范围为1970-2099年
下面简单举几个例子:
"0 0 12 * * ?"    每天中午十二点触发
"0 15 10 ? * *"    每天早上10:15触发
"0 15 10 * * ?"    每天早上10:15触发
"0 15 10 * * ? *"    每天早上10:15触发
"0 15 10 * * ? 2005"    2005年的每天早上10:15触发
"0 * 14 * * ?"    每天从下午2点开始到2点59分每分钟一次触发
"0 0/5 14 * * ?"    每天从下午2点开始到2:55分结束每5分钟一次触发
"0 0/5 14,18 * * ?"    每天的下午2点至2:55和6点至6点55分两个时间段内每5分钟一次触发
"0 0-5 14 * * ?"    每天14:00至14:05每分钟一次触发
"0 10,44 14 ? 3 WED"    三月的每周三的14:10和14:44触发
"0 15 10 ? * MON-FRI"    每个周一、周二、周三、周四、周五的10:15触发

再放一个生成器地址:http://cron.qqe2.com/
  • fixedRate属性:该属性的含义是上一个调用开始后再次调用的延时(不用等待上一次调用完成),这样就会存在重复执行的问题,所以不是建议使用,但数据量如果不大时在配置的间隔时间内可以执行完也是可以使用的。
  • fixedDelay属性:该属性的功效与fixedRate则是相反的,配置了该属性后会等到方法执行完成后延迟配置的时间再次执行该方法。
  • initialDelay属性:该属性跟fixedDelay、fixedRate有着密切的关系,该属性的作用是第一次执行延迟时间,只是做延迟的设定,并不会控制其他逻辑,所以要配合fixedDelay或者fixedRate来使用。

启动Spring Boot应用,观察控制台输出。
如果执行my-test02,哪么my-test01会等一分钟后才执行,因为要等test02执行完才执行。
是不是刷新了世界观,按常理my-test01和my-test02各自执行自己的,为什么会干扰?
是因为@Scheculed默认的线程池是单线程的,任务放在delayQueue队列,排队执行的,所以才会出现等待情况,解决这个问题的办法就是把默认线程改成多线程的。

修改@Scheculed默认线程池为多线程

package com.foreverchan.springboot.config;
 
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.SchedulingConfigurer;
import org.springframework.scheduling.config.ScheduledTaskRegistrar;
 
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.ThreadFactory;
 
/**
 * 修改Spring Scheculed默认线程池
 *
 * @author ForeverChan
 * @date 2019/5/18 18:47
 */
@Configuration
public class ScheduleConfig implements SchedulingConfigurer {
 
    @Override
    public void configureTasks(ScheduledTaskRegistrar scheduledTaskRegistrar) {
        scheduledTaskRegistrar.setScheduler(new ScheduledThreadPoolExecutor(10,
                new ThreadFactory() {
                    @Override
                    public Thread newThread(Runnable r) {
                        return new Thread(r, "my-schedule-pool");
                    }
                }));
    }
}

修改默认线程池为多线程,这里给了10个线程。然后再次启动Spring Boot,我们会发现test01一秒执行一次,test02该等一分钟还是等一分钟,两个任务之间就不会出现等待现象。

二、只使用的注解: @Scheduled 不用 @EnableScheduling

引入spring-boot-starter-actuator

<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-actuator</artifactId>
	<version>1.5.13.RELEASE</version>
</dependency>

去掉@EnableScheduling

/**
 * Spring Boot启动类
 *
 * @author ForeverChan
 * @date 2019/5/18 16:54
 */
@SpringBootApplication
//@EnableScheduling
public class MyBootApplication {
    public static void main(String[] args) {
        SpringApplication.run(MyBootApplication .class, args);
    }
}

@Scheduled注解标识任务

package com.foreverchan.springboot.task;
 
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
 
/**
 * 通过@Scheduled创建任务
 * @author ForeverChan
 * @date 2019/5/18 16:54
 */
@Component
public class MyTestTask {
 	/**
 	 * 每隔一秒执行一次任务test01
 	 */
    @Scheduled(fixedDelay = 1000)
    public void test01() {
        System.out.println("my-test01 start");
        System.out.println("执行业务逻辑...");
        System.out.println("my-test01 end");
    }
 	/**
 	 * 每隔一秒执行一次任务test02
 	 */
    @Scheduled(fixedDelay = 1000)
    public void test02() {
        System.out.println("my-test02 start");
        try {
        	//睡1分钟
            Thread.sleep(60 * 1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("my-test02 end");
    }
}
  • 5
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值