SpringBoot创建定时任务

本文详细介绍了SpringBoot中定时任务的创建与管理,包括基于注解的静态定时任务和基于接口的动态定时任务,以及如何利用多线程提高定时任务的执行效率。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

静态:基于注解

(1)在 main 中(这里就是启动类)类声明开启定时任务的注解 @EnableScheduling:

package com.springboot20.xdclass.springboot.demo2;

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

@SpringBootApplication
@EnableScheduling    //开启定时任务注解
public class Application {

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

}

(2)自定义一个定时任务业务类TestTask.java:
编写定时任务注解 @Scheduled

package com.springboot20.xdclass.springboot.demo2.task;

import java.util.Date;

import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

/**
* 功能描述:定时任务业务类
* @author caoxianshuo
*
*/
@Component
public class TestTask {

   // 注意:定时方法返回值只能是void且不能有传入参数
   @Scheduled(fixedRate=2000)
   public void testTask(){
   	System.out.println("当前时间:"+new Date());
   }
   
}

注意:
“ fixedDelay: 每次方法执行完毕后,等待5s再执行此方法,
同时只能有一个线程运行此方法 ”

@Scheduled(fixedDelay=5000)

“ fixedRate: 每隔5s调用一次此方法,无论之前的方法是否执行完毕,
同时可能有N个线程执行此方法 ”

@Scheduled(fixedRate=5000)

“ initialDelay: 第一次调用此方法前的等待时间 ”

@Scheduled(initialDelay=1000, fixedRate=5000)

“ cron:通过cron配置值 ”

/**
 * 支持cron语法:
 * 每个参数的意义分别是: second, minute, hour, day of month, month, day of week    
 * 
 * 如下:周一至周五,每隔5s执行一次方法
 */
 @Scheduled(cron="*/5 * * * * SUN-MON")

(3)执行测试结果:
在这里插入图片描述
显然,使用@Scheduled 注解很方便,但缺点是当我们调整了执行周期的时候,需要重启应用才能生效,这多少有些不方便。为了达到实时生效的效果,可以使用接口来完成定时任务。

动态:基于接口

(1)整合持久层框架Mybatis,连接数据库

(2)添加数据库记录:

开启本地数据库mysql,随便打开查询窗口,然后执行脚本内容,如下:

DROP DATABASE IF EXISTS `socks`;
CREATE DATABASE `socks`;
USE `SOCKS`;
DROP TABLE IF EXISTS `t_cron`;
CREATE TABLE `t_cron`  (
 `cron_id` varchar(30) NOT NULL PRIMARY KEY,
 `cron` varchar(30) NOT NULL  
);
INSERT INTO `cron` VALUES ('1', '0/10 * * * * ?');

在这里插入图片描述

(3)创建定时器:
数据库准备好数据之后,我们编写定时任务,注意这里添加的是TriggerTask,目的是循环读取我们在数据库设置好的执行周期,以及执行相关定时任务的内容。
新建一个实现SchedulingConfigurer接口的实体类MyScheduleTask,具体代码如下:

package com.springboot20.xdclass.springboot.demo2.task;

import java.util.Date;

import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Select;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.SchedulingConfigurer;
import org.springframework.scheduling.config.ScheduledTaskRegistrar;
import org.springframework.scheduling.support.CronTrigger;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

/**
* 功能描述:基于接口形式实现动态定时任务
* @author caoxianshuo
*
*/
@Component
@Configuration // 主要用于标记配置类,兼具Component的效果
@EnableScheduling // 开启定时任务
public class MyScheduleTask implements SchedulingConfigurer {

   // 定义一个内部Mapper接口类
   @Mapper
   public interface CronMapper {

   	@Select("Select cron from t_cron limit 1")
   	public String getCron();

   }

   // 注入Mapper
   @Autowired
   private CronMapper cronMapper;

   /**
    * 功能描述:执行定时任务
    */
   @Override
   public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {

   	taskRegistrar.addTriggerTask(
   			// 1.添加任务内容(Runnable)
   			() -> System.out.println("执行动态定时任务: " + new Date()),
   			// 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);
   			}
   	);

   }

}

控制台执行结果:
在这里插入图片描述
然后打开Navicat ,将执行周期修改为每6秒执行一次,如图:
在这里插入图片描述
查看控制台,发现执行周期已经改变,并且不需要我们重启应用,十分方便。如图:
在这里插入图片描述
注意: 如果在数据库修改时格式出现错误,则定时任务会停止,即使重新修改正确;此时只能重新启动项目才能恢复。

多线程定时任务:

基于注解设定多线程定时任务

package com.springboot20.xdclass.springboot.demo2.task;

import java.time.LocalDateTime;

import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

@Component
@EnableScheduling //开启定时任务
@EnableAsync //开启多线程
public class MyThreadScheduleTask {

   @Async
   @Scheduled(fixedDelay = 1000) //间隔1秒
   public void first() throws InterruptedException{
   	 System.out.println("第一个定时任务开始 : " + LocalDateTime.now().toLocalTime() + "\r\n线程 : " + Thread.currentThread().getName());
        System.out.println();
        Thread.sleep(1000 * 10);
   }
   
   @Async
   @Scheduled(fixedDelay = 2000) //间隔1秒
   public void second(){
   	 System.out.println("第二个定时任务开始 : " + LocalDateTime.now().toLocalTime() + "\r\n线程 : " + Thread.currentThread().getName());
        System.out.println();
   }
   
}

启动测试:
在这里插入图片描述

从控制台可以看出,第一个定时任务和第二个定时任务互不影响;

并且,由于开启了多线程,第一个任务的执行时间也不受其本身执行时间的限制,所以需要注意可能会出现重复操作导致数据异常。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值