解决Spring定时任务疑难杂症指南

af752cadc4c06c5d14af52af58b1cbc0.png

定时任务是在指定的时间点执行预定义的操作,例如在特定时间点发送邮件、执行某个操作或查询数据库等。在 Java 开发中,我们经常使用定时任务来实现一些周期性的任务,比如统计网站的访问量、处理后台任务等。然而,有时候我们会遇到定时任务不执行的问题。本文将介绍可能导致定时任务不执行的原因以及解决方法。

b8d697c5cc3cda2fa3a21f6378ee881e.png

一、定时任务配置问题

在 Spring Boot 中,我们通常使用 @Scheduled 注解来配置定时任务。如果定时任务不执行,首先需要检查 @Scheduled 注解的配置是否正确。例如,我们使用 cron 表达式来配置定时任务的执行规则,如果表达式有误,则定时任务将无法执行。因此,我们需要检查 @Scheduled 注解中的配置参数是否正确。

另外,还需要检查 @Scheduled 注解所标注的方法是否正确。如果方法本身存在问题,比如方法无法访问、抛出异常等,也会导致定时任务无法执行。

二、线程池配置问题

在 Spring Boot 中,定时任务的执行需要使用线程池。如果线程池的配置不正确,可能会导致定时任务无法执行。例如,线程池的核心线程数过小,可能会导致线程池中的所有线程都在执行其他任务,而无法执行定时任务。因此,我们需要检查线程池的配置是否正确,并根据实际需求调整线程池的配置参数。

三、任务执行逻辑问题

如果定时任务的执行逻辑存在问题,可能会导致任务无法正常执行。例如,在任务执行时抛出了异常、任务的执行时间过长等,都可能导致任务无法正常执行。在这种情况下,我们需要检查任务的执行逻辑,并对其进行调整或修复。

四、定时任务触发时间问题

定时任务的触发时间也是一个需要注意的问题。如果定时任务的触发时间设置不正确,可能会导致任务无法正常执行。例如,如果定时任务的触发时间设置在当前时间之后的某个时间点,那么该任务将无法立即执行。因此,我们需要检查定时任务的触发时间是否正确,并根据实际需求进行调整。

五、系统或环境问题

最后,还需要考虑系统或环境问题。例如,操作系统或 Java 环境配置不正确、应用程序的依赖项缺失等,都可能导致定时任务无法执行。在这种情况下,我们需要检查系统或环境的配置是否正确,并对其进行调整或修复。

54e7620adb4cd6dab0da37a2bc737a14.png

具体示例

一、排查代码中添加的定时任务步骤是否正确

  1. 启动类上加 @EnableScheduling 注解

  2. 定时任务类上加@Component

  3. 定时方法上加@Scheduled

@Scheduled(cron = "0 19 16 * * ?")
public void cron() {
    log.info("定时任务开启:---");
}

二、排查是否任务阻塞,如果定时任务出现异常阻塞后,将不会在次执行

解决:进行try…catch异常抛出

三、java中多个@Scheduled定时器不执行

原因是:@Scheduled注解会在默认情况下以单线程的方式执行定时任务。
这个“单线程”指两个方面:

  1. 如果一个定时任务执行时间大于其任务间隔时间,那么下一次将会等待上一次执行结束后再继续执行。

  2. 如果多个定时任务在同一时刻执行,任务会依次执行。

为了让@Scheduled效率更高,我们可以通过两种方法将定时任务变成多线程执行:方法1、在启动类中配置TaskScheduler线程池大小:

public TaskScheduler taskScheduler() {
    ThreadPoolTaskScheduler taskScheduler = new ThreadPoolTaskScheduler();
    taskScheduler.setPoolSize(10);//不配置默认是1
    return taskScheduler;
}

方法2、利用Spring提供的@Async注解和@EnableAsync注解

@Component
@EnableAsync //开启异步支持
public class TimedTask{
@Async // 对某个方法进行异步执行
@Scheduled(initialDelay = 1,fixedDelay=10000)//initialDelay 在容器启动后,延迟1毫秒再执行一次定时器
public void aa() {
//执行业务逻辑
}


@Async
@Scheduled(initialDelay = 1,fixedDelay=10000)//fixedDelay  以上一次方法执行完开始算起,如上一次方法执行阻塞住了,那么直到上一次执行完,并间隔给定的时间后,执行下一次
public void bb() {
//执行业务逻辑
}

这里并没有结束。之所以出现这个问题,是因为写法问题。

0b7a5ebe65db157b205b4e65a5098ae2.jpeg

下面我们给出 Spring Scheduled 定时任务的标准写法。强烈建议大家都使用如下步骤和配置,后期可以避免很多棘手问题。

  1. 在 Spring Boot 项目中,添加依赖项。在 pom.xml 文件中添加以下内容:

<dependency>  
    <groupId>org.springframework.boot</groupId>  
    <artifactId>spring-boot-starter</artifactId>  
</dependency>
  1. 在 @SpringBootApplication 注解中添加 @EnableScheduling,开启定时任务的注解。例如:

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

3. 创建一个定时任务类,实现需要执行的任务逻辑。例如:

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


@Component  
public class ScheduledTasks {  


    @Scheduled(cron = "0 0 * * * ?") // 每小时执行一次  
    public void reportCurrentTime() {  
        System.out.println("Current time is " + new java.util.Date());  
    }  
}

在这个例子中,我们使用 @Scheduled 注解指定了一个 cron 表达式,表示每小时的第 0 分钟执行任务。reportCurrentTime() 方法将在每小时的第 0 分钟输出当前时间。

  1. 在 application.properties 或 application.yml 文件中配置定时任务的调度器。例如:

在 application.properties 文件中:

# 设置定时任务使用默认的线程池  
spring.scheduling.thread-pool.core-pool-size=10  
spring.scheduling.thread-pool.max-pool-size=50  
spring.scheduling.thread-pool.queue-capacity=1000000000

在 application.yml 文件中:

spring:  
  scheduling:  
    thread-pool:  
      core-pool-size: 10  
      max-pool-size: 50  
      queue-capacity: 1000000000

这里我们设置了定时任务使用的线程池的配置。可以根据实际需求进行调整。

5. 运行程序,启动 Spring Boot 应用。此时,reportCurrentTime() 方法将按照配置的定时规则执行,并输出当前时间。

6. 可以通过查看日志、监控系统日志或使用工具等方式来查看定时任务的执行情况。如果遇到问题,可以根据错误信息进行排查和调试。

总的来说,Spring的scheduled还是比较方便使用的,希望本文能帮到您!如果使用过程中有什么问题,欢迎发消息给我们!

** 欢迎关注 **

  • 9
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值