SpringBoot定时任务@Schedule注解单线程阻塞

@Scheduled注解

@Scheduled注解是spring boot提供的用于定时任务控制的注解,主要用于控制任务在某个指定时间执行,或者每隔一段时间执行.

配置@Scheduled主要有三种配置执行时间的方式(cron/fixedRate/fixedDelay)。它的配置一共有8个参数,需要配合@EnableScheduling注解使用(在启动类上,声明 @EnableScheduling,表示开启定时任务;或者在定时任务的每个类上都加上@EnableScheduling注解)。

cron表达式

该参数接收一个cron表达式,cron表达式是一个字符串,以5或6个空格隔开,分开共6或7个域,每一个域代表一个含义。

cron 表达式在线生成地址:https://cron.qqe2.com/
语法

[秒] [分] [小时] [日] [月] [周] [年]

常用通配符说明
*:表示所有值。 例如:在分的字段上设置 *,表示每一分钟都会触发。
?:表示不指定值。使用的场景为不需要关心当前设置这个字段的值。例如:要在每月的10号触发一个操作,但不关心是周几,所以需要周位置的那个字段设置为“?”, 具体设置为 0 0 0 10 * ?

例如:@Scheduled(cron = "0 0 1 * * ?") // 每天凌晨一点各执行一次(使用的时候直接放在定时任务方法上即可)

fixedRate

该配置表示上一次执行时间后距离多长时间再执行;
例如:

@Scheduled(fixedRate = 5000) //上一次开始执行时间点之后5秒再执行
@Scheduled(fixedRate = 1000 * 10) //10秒发送一次

与cron表达式区别:该配置在实际使用中(本地配置后),重启tomcat即可生效;而cron表达式只能等到约定时间后才能生效;

fixedDelay

上一次执行完毕时间点之后多长时间再执行。

@Scheduled(fixedDelay = 5000)

上面介绍了,几种参数,下面记录一下我在项目中遇到的问题

场景案例:

新项目中,有个天气需要每个一个小时更新一下,调用外部接口。这里我准备用@Scheduled定时任务。

但是想到一个问题:外部接口不稳定,存在一种情况线程任务启动了,一直在执行中,长时间不结束,定时任务周期到了,由于@Scheduled是单线程,导致数据没有得到及时更新;同时,假如存在多个定时任务,有可能导致其他任务不能及时执行

解决方案:

方案一:使用@Async注解实现异步任务

方案二:配置线程池

我选用,方案二,配置线程池代码,这里实现方式可以是多样的。这里做了一个全局配置,利用线程池,去支撑单线程定时任务

/**
 * 配置线程池
 * 防止定时任务 @Scheduled 单线程阻塞
 */
@Configuration
public class ScheduledConfig implements SchedulingConfigurer {
    @Override
    public void configureTasks(ScheduledTaskRegistrar scheduledTaskRegistrar) {
        scheduledTaskRegistrar.setScheduler(Executors.newScheduledThreadPool(5));
    }
}

两种方式各有优缺点:

比较方案一方案二
优点注解方式使用简单,代码量少配置灵活,线程数可控
缺点线程数不可控,可能存在资源浪费需要增加编码

补充:

定时任务调度框架:Timer,ScheduledExecutorService,SpringTask,Quartz,xxl-job,elastic-job

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值