Scheduled定时任务到点不执行

项目场景:

  在系统中,通过@Scheduled创建了10几个定时任务,对系统数据进行统计、数据清理、缓存初始化等操作。


问题描述

    在系统中,通过@Scheduled方式创建了10多个定时任务,定义的cron表达式有几个是cron = "0 0/5 * * * ?",有些是0 */30 * * * ?。有个定时任务是每5分钟对mongodb存储的API接口调用情况按天、小时、日等维度做统计数据。系统上线一段时间之后,API调用统计经常不是每隔5分钟执行,导致统计数据不准


原因分析:

  统计的定时任务增加打印日志,打印每次进入定时任务的时间,定位哪个时间段没有执行任务。通过打印日志,发现xx:30分钟左右的时候,经常不会执行,怀疑是0 */30 * * * ?对它有影响。

经过排查,发现有一个在30分执行的定时任务,执行时间需要几分钟。通过查资料,知道@Scheduled定时任务默认使用单线程模式。  30分钟的时候,线程被阻塞,导致一些任务到点不执行。

@Scheduled定时任务默认使用单线程模式。 系统中多于1个定时任务,是会排队执行,如果有任务执行时间长,会阻塞后面任务的执行。


解决方案:

给严格要求到点执行的定时任务,指定特定的线程池。例如下面的例子

(1)初始化一个线程

@Configuration
@EnableAsync
public class ThreadPoolConfig4DAPI {@Bean("apiScheduleThreadPool")
public Executor apiScheduleThreadPool() {
    ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
    executor.setCorePoolSize(2);
    executor.setMaxPoolSize(4);
    executor.setQueueCapacity(Integer.MAX_VALUE);
    executor.setKeepAliveSeconds(60);
    executor.setThreadNamePrefix("apiSchedule-");
    // 线程池拒绝策略;
    /**
     * AbortPolicy:丢弃并抛出异常
     * DiscardPolicy:丢弃但不抛异常
     * DiscardOldestPolicy:丢弃最老的,把新的加进去
     * CallerRunsPolicy:主线程运行
     */
    executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
    executor.initialize();
    return executor;
}
}
(2)@Scheduled指定线程池
/**
 * 日志统计: 不加异步可能到点不执行
 * @Scheduled定时任务默认使用单线程模式导致的问题;一旦有一个定时任务比较耗时,就会影响到其它定时任务按时执行。
 **/
@Async("apiScheduleThreadPool")
@Scheduled(cron = "0 0/5 * * * ?") // 0 14 14 * * ? 5 0 0 * * ?
@RedisLock(value = "Bcrz2DytjTask", leaseTime = 240, waitTime = 240)
public void dailyTask() {

}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

爱晒太阳的小老鼠

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

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

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

打赏作者

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

抵扣说明:

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

余额充值