如何解决Springboot定时任务遇到的问题

这篇文章给大家分享的是有关如何解决Springboot定时任务遇到的问题的内容。小编觉得挺实用的,因此分享给大家做个参考。一起跟随小编过来看看吧。

创新互联公司,专注为中小企业提供官网建设、营销型网站制作、响应式网站开发、展示型网站建设、网站制作等服务,帮助中小企业通过网站体现价值、有效益。帮助企业快速建站、解决网站建设与网站营销推广问题。

前言:在使用Springboot整合定时任务,发现当某个定时任务执行出现执行时间过长的情况时会阻塞其他定时任务的执行。

问题定位

后续通过翻查Springboot的文档以及打印日志(输出当前线程信息)得知问题是由于Springboot默认使用只要1个线程处理定时任务。

问题复盘

需要注意示例的Springboot版本为2.1.3.RELEASE。

关键pom文件配置

    
    
        org.springframework.boot
        spring-boot-starter-parent
        2.1.3.RELEASE
         
    
    
    ...省略非关键配置
    
    
    
        
            org.springframework.boot
            spring-boot-starter
        

        
            org.springframework.boot
            spring-boot-starter-test
            test
        
    

定时任务

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

/**
 * 定时任务
 * @author RJH
 * create at 2019-03-29
 */
@Component
public class SimpleTask {

    private static Logger logger= LoggerFactory.getLogger(SimpleTask.class);

    /**
     * 执行会超时的任务,定时任务间隔为5000ms(等价于5s)
     */
    @Scheduled(fixedRate = 5000)
    public void overtimeTask(){
        try {
            logger.info("current run by overtimeTask");
            //休眠时间为执行间隔的2倍
            Thread.sleep(10000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    /**
     * 正常的定时任务
     */
    @Scheduled(fixedRate = 5000)
    public void simpleTask(){
        logger.info("current run by simpleTask");
    }
}

启动类

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

@SpringBootApplication
@EnableScheduling
public class TaskDemoApplication {

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

}

运行结果

...省略非关键信息
2019-03-29 21:22:38.410  INFO 59731 --- [   scheduling-1] com.rjh.task.SimpleTask                  : current run by simpleTask
2019-03-29 21:22:38.413  INFO 59731 --- [   scheduling-1] com.rjh.task.SimpleTask                  : current run by overtimeTask
2019-03-29 21:22:48.413  INFO 59731 --- [   scheduling-1] com.rjh.task.SimpleTask                  : current run by simpleTask
2019-03-29 21:22:48.414  INFO 59731 --- [   scheduling-1] com.rjh.task.SimpleTask                  : current run by overtimeTask
2019-03-29 21:22:58.418  INFO 59731 --- [   scheduling-1] com.rjh.task.SimpleTask                  : current run by simpleTask
2019-03-29 21:22:58.418  INFO 59731 --- [   scheduling-1] com.rjh.task.SimpleTask                  : current run by overtimeTask
2019-03-29 21:23:08.424  INFO 59731 --- [   scheduling-1] com.rjh.task.SimpleTask                  : current run by simpleTask
2019-03-29 21:23:08.424  INFO 59731 --- [   scheduling-1] com.rjh.task.SimpleTask                  : current run by overtimeTask
2019-03-29 21:23:18.425  INFO 59731 --- [   scheduling-1] com.rjh.task.SimpleTask                  : current run by simpleTask
2019-03-29 21:23:18.426  INFO 59731 --- [   scheduling-1] com.rjh.task.SimpleTask                  : current run by overtimeTask
...

结果分析

由运行结果可以看出:

  1. 每次定时任务的运行都是由scheduling-1这个线程处理
  2. 正常运行的simpleTaskovertimeTask阻塞导致了运行间隔变成了10

后面通过查阅Springboot的文档也得知了定时任务默认最大运行线程数为1

解决方案

由于使用的Springboot版本为2.1.3.RELEASE,所以有两种方法解决这个问题

使用Springboot配置

在配置文件中可以配置定时任务可用的线程数:

## 配置可用线程数为10
spring.task.scheduling.pool.size=10

自定义定时任务的线程池

使用自定义的线程池代替默认的线程池

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

/**
 * 定时任务配置类
 * @author RJH
 * create at 2019-03-29
 */
@Configuration
public class ScheduleConfig {

    /**
     * 此处方法名为Bean的名字,方法名无需固定
     * 因为是按TaskScheduler接口自动注入
     * @return
     */
    @Bean
    public TaskScheduler taskScheduler(){
        // Spring提供的定时任务线程池类
        ThreadPoolTaskScheduler taskScheduler=new ThreadPoolTaskScheduler();
        //设定最大可用的线程数目
        taskScheduler.setPoolSize(10);
        return taskScheduler;
    }
}

感谢各位的阅读!关于如何解决Springboot定时任务遇到的问题就分享到这里了,希望以上内容可以对大家有一定的帮助,让大家可以学到更多知识。如果觉得文章不错,可以把它分享出去让更多的人看到吧!


文章标题:如何解决Springboot定时任务遇到的问题
当前URL:http://scjbc.cn/article/pgppds.html

其他资讯