SpringBoot之定时任务

在Spring Boot中,定时任务是常用的功能,主要通过@Scheduled注解来实现。Spring提供了多种定时任务的配置方式,包括固定速率、固定延迟、Cron表达式等。以下是如何在Spring Boot中使用定时任务的详细说明。
1. 引入依赖
在Spring Boot中,定时任务通常不需要额外的依赖,Spring框架已经内置了相关功能。确保你的spring-boot-starter包含了必要的依赖项。
2. 启用定时任务
要启用定时任务功能,需要在主应用程序类或配置类上添加@EnableScheduling注解。

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

@SpringBootApplication
@EnableScheduling
public class ScheduledTasksApplication {
    public static void main(String[] args) {
        SpringApplication.run(ScheduledTasksApplication.class, args);
    }
}

3. 使用 @Scheduled 注解定义定时任务

@Scheduled注解用于标注定时任务的方法。这个方法不能有返回值,而且不能接受参数。
3.1 固定速率执行
fixedRate参数用于定义任务以固定的时间间隔执行,不考虑任务的执行时间。

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

@Component
public class FixedRateTask {

    @Scheduled(fixedRate = 5000)
    public void performTask() {
        System.out.println("Fixed rate task - " + System.currentTimeMillis() / 1000);
    }
}

上述示例表示每5秒执行一次任务。
3.2 固定延迟执行
fixedDelay参数用于定义任务在前一次执行完成后,再等待指定的时间间隔后执行。

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

@Component
public class FixedDelayTask {

    @Scheduled(fixedDelay = 5000)
    public void performTask() {
        System.out.println("Fixed delay task - " + System.currentTimeMillis() / 1000);
    }
}

上述示例表示在上一次任务执行完成后等待5秒再执行。
3.3 首次延迟执行
initialDelay参数用于指定任务在启动时延迟多少时间后再首次执行。它可以与fixedRate或fixedDelay一起使用。
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

@Component
public class InitialDelayTask {

@Scheduled(initialDelay = 10000, fixedRate = 5000)
public void performTask() {
    System.out.println("Initial delay task - " + System.currentTimeMillis() / 1000);
}

}
上述示例表示任务在应用启动10秒后首次执行,之后每5秒执行一次。
3.4 使用 Cron 表达式
cron参数可以通过Cron表达式定义更加复杂的定时任务规则。

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

@Component
public class CronTask {
    @Scheduled(cron = "0 0/1 * * * ?")
    public void performTask() {
        System.out.println("Cron task - " + System.currentTimeMillis() / 1000);
    }
}

上述示例表示每分钟的开始执行任务。Cron表达式语法为:秒 分 小时 日 月 星期 [年]。
4. 管理和取消定时任务
Spring Boot 定时任务默认是单线程执行,如果有多个任务并发执行,可能会出现阻塞。可以通过配置线程池来管理任务的并发执行。
4.1 配置线程池

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;

@Configuration
public class TaskSchedulerConfig {

    @Bean
    public ThreadPoolTaskScheduler taskScheduler() {
        ThreadPoolTaskScheduler taskScheduler = new ThreadPoolTaskScheduler();
        taskScheduler.setPoolSize(10);
        taskScheduler.setThreadNamePrefix("Scheduled-Task-");
        return taskScheduler;
    }
}

4.2 动态取消任务
通过手动管理任务的执行,可以动态启动或停止任务。

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
import org.springframework.scheduling.support.CronTrigger;
import org.springframework.stereotype.Component;

import java.util.concurrent.ScheduledFuture;

@Component
public class DynamicTaskManager {

    @Autowired
    private ThreadPoolTaskScheduler taskScheduler;

    private ScheduledFuture<?> future;

    public void startTask() {
        future = taskScheduler.schedule(() -> System.out.println("Dynamic task - " + System.currentTimeMillis() / 1000),
                new CronTrigger("0/10 * * * * *")); // 每10秒执行一次
    }

    public void stopTask() {
        if (future != null) {
            future.cancel(true);
        }
    }
}
  1. 注意事项
    单线程问题: Spring的默认定时任务是单线程的,这意味着如果一个任务阻塞,其他任务将无法执行。通过配置线程池可以避免这个问题。
    异常处理: 如果定时任务抛出未处理的异常,可能会导致任务中止,确保对可能的异常进行捕获和处理。
    精度问题: 定时任务的精度可能会受到系统时间调度的影响,通常在毫秒级别。
    通过以上方式,你可以在Spring Boot中灵活地实现定时任务,并根据需求进行管理和优化。

多线程定时任务

//@Component注解用于对那些比较中立的类进行注释;
//相对与在持久层、业务层和控制层分别采用 @Repository、@Service 和 @Controller 对分层中的类进行注释

@Component
@EnableScheduling   // 1.开启定时任务
@EnableAsync        // 2.开启多线程
public class MultithreadScheduleTask {

        @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)
        public void second() {
            System.out.println("第二个定时任务开始 : " + LocalDateTime.now().toLocalTime() + "\r\n线程 : " + Thread.currentThread().getName());
            System.out.println();
        }
    }
@Configuration
 public class MyTheadPoolConfig {
     @Bean
     public TaskExecutor taskExecutor() {
         ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
         //设置核心线程数
         executor.setCorePoolSize(10);
         //设置最大线程数
         executor.setMaxPoolSize(20);
         //缓冲队列200:用来缓冲执行任务的队列
         executor.setQueueCapacity(200);
         //线程活路时间 60 秒
         executor.setKeepAliveSeconds(60);
         //线程池名的前缀:设置好了之后可以方便我们定位处理任务所在的线程池
         // 这里我继续沿用 scheduling 默认的线程名前缀
         executor.setThreadNamePrefix("nzc-create-scheduling-");
         //设置拒绝策略
         executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
         executor.setWaitForTasksToCompleteOnShutdown(true);
         return executor;
     }
 
 }
 /**
  * @description:
  * @author: Ning Zaichun
  */
 @Slf4j
 @Component
 @EnableScheduling
 public class ScheduleService {
 
     @Autowired
     TaskExecutor taskExecutor;
 
     @Scheduled(cron = "0/5 * * * * ? ")
     public void testSchedule() {
         CompletableFuture.runAsync(()->{
             try {
                 Thread.sleep(10000);
                 log.info("当前执行任务的线程号ID===>{}", Thread.currentThread().getId());
             } catch (Exception e) {
                 e.printStackTrace();
             } 
         },taskExecutor);
     }
 }
/**
  * @description:
  * @author: Ning Zaichun
  */
 @Slf4j
 @Component
 @EnableAsync
 @EnableScheduling
 public class ScheduleService {
 
     @Autowired
     TaskExecutor taskExecutor;
 
     @Async(value = "taskExecutor")
     @Scheduled(cron = "0/5 * * * * ? ")
     public void testSchedule() {
             try {
                 Thread.sleep(10000);
                 log.info("当前执行任务的线程号ID===>{}", Thread.currentThread().getId());
             } catch (Exception e) {
                 e.printStackTrace();
             } 
     }
 }

Spring Boot 如何通过配置文件开启关闭定时任务

在 Spring Boot 中,可以通过配置文件来控制定时任务的开启和关闭。以下是一种常见的实现方式:

  1. 在application.properties或application.yml中添加以下配置项:
    #开启/关闭定时任务,默认为开启
    scheduling.enabled=true
  2. 在定时任务的类上使用@ConditionalOnProperty注解,并设置havingValue属性为配置文件中对应的值:
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

@Component
@ConditionalOnProperty(name = "scheduling.enabled", havingValue = "true", matchIfMissing = true)
public class MyScheduledTask {

    @Scheduled(cron = "0 0 0 * * *") // 每天0点触发
    public void myTask() {
        // 执行定时任务的逻辑
    }
}

在上述示例中:
● scheduling.enabled是配置文件中的属性,控制定时任务的开启和关闭。默认值为true,表示开启定时任务。
● MyScheduledTask是一个定时任务的类,使用@Component注解标识为一个组件,并且使用@ConditionalOnProperty注解来根据配置文件中的属性值进行条件判断。
● @ConditionalOnProperty注解的name属性指定了要匹配的属性名,havingValue属性指定了与之匹配的属性值。如果配置文件中的scheduling.enabled属性值与havingValue的值相匹配(即为true),则定时任务会被启用;如果不匹配,则定时任务不会被启用。
● @Scheduled注解用于指定定时任务的执行时间表达式。
通过这种方式,你可以根据需要在配置文件中灵活地开启或关闭定时任务。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

思静鱼

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值