问小白 wenxiaobai
资讯
历史
科技
环境与自然
成长
游戏
财经
文学与艺术
美食
健康
家居
文化
情感
汽车
三农
军事
旅行
运动
教育
生活
星座命理

SpringBoot 定时任务实践:从入门到多线程解决方案

创作时间:
作者:
@小白创作中心

SpringBoot 定时任务实践:从入门到多线程解决方案

引用
CSDN
1.
https://blog.csdn.net/festone000/article/details/137496081

Q1. SpringBoot怎样创建定时任务?

创建SpringBoot定时任务非常简单,只需在需要执行定时任务的方法上添加@Scheduled注解,并指定cron表达式即可。

@Scheduled(cron = ".....")

Q2. 如上所示创建了定时任务却未能执行是为什么?

如果确认cron表达式没有写错,但定时任务仍然未能执行,可能是由于启动类缺少@EnableScheduling注解。确保在启动类中添加此注解。

Q3. 多个定时任务,未能严格按照指定的时间执行,为什么?

在SpringBoot中,定时任务默认是单线程执行的。如果多个定时任务需要在不同时间点执行,但前一个任务执行时间过长,会导致后续任务延迟执行。

例如,有4个定时任务分别在每天凌晨1点、2点、3点和4点执行。如果第一个任务执行了1.5小时,那么第二个任务将在2点半开始执行,依此类推。

Q4. 如何确保定时任务在特定时间执行?

要确保定时任务在特定时间执行,可以使用多线程。具体步骤如下:

Step 1:初始化线程池

创建一个线程池配置类SchedulerConfig,并实现SchedulingConfigurer接口。

package cn.xxx.starter.config;

import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.SchedulingConfigurer;
import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
import org.springframework.scheduling.config.ScheduledTaskRegistrar;

@Configuration
public class SchedulerConfig implements SchedulingConfigurer {
    @Resource
    private ThreadPoolTaskScheduler threadPoolTaskScheduler;

    @Override
    public void configureTasks(ScheduledTaskRegistrar scheduledTaskRegistrar) {
        scheduledTaskRegistrar.setTaskScheduler(threadPoolTaskScheduler);
    }
}

创建线程池配置类ThreadPoolTaskSchedulerConfig,并配置线程池参数。

package cn.xxx.starter.config;

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

@Configuration
@EnableAsync
public class ThreadPoolTaskSchedulerConfig {
    private int corePoolSize = 4;

    @Bean
    public ThreadPoolTaskScheduler threadPoolTaskScheduler() {
        ThreadPoolTaskScheduler threadPoolTaskScheduler = new ThreadPoolTaskScheduler();
        threadPoolTaskScheduler.setPoolSize(corePoolSize);
        threadPoolTaskScheduler.setThreadNamePrefix("AsyncJob-thread-");
        threadPoolTaskScheduler.setWaitForTasksToCompleteOnShutdown(true);
        threadPoolTaskScheduler.setAwaitTerminationSeconds(60 * 60);
        threadPoolTaskScheduler.initialize();
        return threadPoolTaskScheduler;
    }
}

Step 2:启动定时任务时指定使用此线程池

在定时任务类中,使用@Async注解指定使用自定义线程池。

package cn.xxx.starter.task.job;

import com.alibaba.fastjson.JSON;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

@Slf4j
@Component
public class Job1 {
    @Async(value = "threadPoolTaskScheduler")
    @Scheduled(cron = "0 30 */1 * * ?")
    public void execute() {
        try {
            //......
        } catch (Exception e) {
            log.error("Job1出错 e = {}, stackTrace = {} ", e.getMessage(), JSON.toJSONString(e.getStackTrace()));
        } finally {
            log.info("Job1结束");
        }
    }
}

通过以上配置,可以确保多个定时任务在指定时间点并行执行,避免因单线程执行导致的延迟问题。

© 2023 北京元石科技有限公司 ◎ 京公网安备 11010802042949号