Springboot中实现定时执行和启动时执行

需求说明

  • 每天定时0点执行清洗任务。
  • 项目启动时执行清洗任务。
  • 不能干扰项目启动。
  • 默认从2023年1月1日开始执行清洗任务。

注意

  • 每一种清洗任务的业务不同,需要注意幂等性问题。

实现思路

  • 使用Scheduled注解完成定时功能。
  • 使用PostConstruct注解设定项目启动时执行。
  • 使用ThreadPoolExecutor执行多线程任务,不影响项目主线程。
  • 使用ApplicationContextAware接口,通过上下文获取bean对象。

代码

  • CleanTaskAble接口。
package com.xxx.scheduling;

import com.xxx.DateUtil;
import com.xxx.ValidUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Date;

public interface CleanTaskAble{

    Logger logger = LoggerFactory.getLogger(CleanTaskAble.class);

    default void runTask() {
        String taskInfor = "cleanTask " + this.getClass().getSimpleName();
        Date lastDate = getLastDate();
        if (ValidUtil.isEmpty(lastDate)) {
            lastDate = DateUtil.parse("2023-01-01 00:00:00", DateUtil.yyyyMMddHHmmssPattern);
        }
        clean(lastDate);
        logger.debug(taskInfor + " end");
    }

    Date getLastDate();

    void clean(Date startDate);
}
  • SchedulingWebConfig调度环境类。
package com.xxx.scheduling;

import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;

import javax.annotation.PostConstruct;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.*;

@Configuration
@EnableScheduling
@Slf4j
public class SchedulingWebConfig implements ApplicationContextAware {

    private final List<CleanTaskAble> taskList = new ArrayList<>(8);

    private final ThreadPoolExecutor exec;

    public SchedulingWebConfig() {
        /*
         * corePoolSize为0,没有及时性要求,设置为0减少内存消耗。
         * maximumPoolSize为4,不需要占用太多的资源;
         * keepAliveTime为60S,意味着线程空闲时间超过60S就会被杀死;
         * LinkedBlockingQueue,可变长度任务队列,最大值为100。
         */
        this.exec = new ThreadPoolExecutor(0, 4,
                60L, TimeUnit.SECONDS,
                new LinkedBlockingQueue<Runnable>(100));
    }

    //每天0点0分0秒定时执行
    @Scheduled(cron = "0 0 0 * * ?")
    public void cleanTasks() {
        log.info("daily tasks start");
        clean();
        log.info("daily tasks end");
    }

    //项目启动时执行
    @PostConstruct
    public void cleanWhenInit() {
        log.info("init tasks start");
        clean();
        log.info("init tasks end");
    }

    //使用线程池,不影响项目主体
    private void clean() {
        log.info("exec infor:" + exec);
        for (CleanTaskAble task : taskList) {
            exec.submit(() -> {
                try {
                    log.info(task.getClass().getSimpleName() + " clean task begin!");
                    task.runTask();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            });
        }
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        taskList.addAll(applicationContext.getBeansOfType(CleanTaskAble.class).values());
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

田秋浩

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

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

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

打赏作者

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

抵扣说明:

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

余额充值