使用springboot时,解决@Scheduled定时器遇到的问题

目录
  • @Scheduled定时器遇到的问题
    • 下面说一下@Scheduled 注解的几个参数
      • 一、可以通过配置文件配置进来的
      • 二、不可通过配置文件配置的 (作用相同)
  • 定时任务@Scheduled使用的那些坑
    • 一、使用的那些坑?
      • 1.单线程
      • 2.@Async和@EnableAsync
    • 二、使用多线程
    • 小结一下

@Scheduled定时器遇到的问题

@Scheduled 这个注解确实给我们带了很大的方便,我们只要加上该注解,并且根据需求设置好就可以使用定时任务了。

但是,我们需要注意的是,@Scheduled 并不一定一定会按时执行。

因为使用@Scheduled 的定时任务虽然是异步执行的,但是,不同的定时任务之间并不是并行的!!!!!!!!

在其中一个定时任务没有执行完之前,其他的定时任务即使是到了执行时间,也是不会执行的,它们会进行排队。

也就是如果你想你不同的定时任务互不影响,到时间就会执行,那么你最好将你的定时任务方法自己搞成异步方法,这样,

定时任务其实就相当于调用了一个线程执行任务,一瞬间就结束了。当然,也可以勉强当做是任务都会定时执行。

下面说一下@Scheduled 注解的几个参数

一、可以通过配置文件配置进来的

使用表达式,该表达式表示每一秒中执行一次。如果上一次方法超过了定时时间还没有执行完,那么下一次定时不会执行,

直到上次方法执行完后,就会立即执行下一次的定时任务

该方式在工程启动的时候,并不会立即执行,会按照定时表达式的规律进行执行。例如这里,就是1秒后才会执行。

@Scheduled(cron="0/1 * * * * ?")   

使用固定速率。该表达式表示每隔一秒钟执行一次。如果上一次方法超过了1秒钟还没执行完,下一次任务也不会执行,直到

上次方法执行完,下次的定时就会立即执行。

该方式在工程启动的时候,会立即执行,接下来会按规律进行执行。

@Scheduled(fixedRateString="1000")   // 单位:毫秒

该方式和上一个的不同在于多加了一个参数,这个参数是一个初始化参数。

加上initialDelayString后,在刚启动的时候,就不会立即执行了,而是会等到10秒之后才会执行,即使fixedRateString才

1秒钟。也会在10秒后才会第一次执行。

注意:initialDelayString不能喝cron组合使用。

@Scheduled(fixedRateString="1000",initialDelayString="10000")

使用固定延迟。该表达式表示每次执行完后一秒再次执行。每一次执行,无论执行多长时间,下一次执行都会在上一次方法

执行完后,再过一秒钟,再次执行。

该方式在工程启动的时候,会立即执行,接下来会按规律进行执行。

@Scheduled(fixedDelayString="1000")

二、不可通过配置文件配置的 (作用相同)

   @Scheduled(fixedRate=1000)      // 它们都是接受一个long类型的参数
   @Scheduled(fixedDelay=1000)
   @Scheduled(fixedRate=1000,initialDelay=10000)

这里粘贴一下cron表达式的规则:

字段 允许值 允许的特殊字符
0-59 , - * /
小时 0-23 , - * /
日期 1-31 , - * ? / L W C
月份 1-12 或者 JAN-DEC , - * /
星期 1-7 或者 SUN-SAT , - * ? / L C #
年(可选) 留空, 1970-2099 , - * /

定时任务@Scheduled使用的那些坑

@Scheduled是spring自带的注解,默认是单线程,常用作定时任务使用,但是如果是集群版的机器的话,就考虑加上分布式锁或者使用分布式定时任务代替。

一、使用的那些坑?

1.单线程

因为@Scheduled默认使用的是单线程,如果有两个任务A和B,那么任务A要是阻塞了,任务B就无法执行。

2.@Async和@EnableAsync

为了解决单线程带来的线程阻塞问题,我们可以使用@Async和@EnableAsync两个注解采用异步的方式去处理,这样就是不同的线程去执行,但是这种方式也带来一个新的问题,那就是如果任务A的任务执行时间>任务调度周期时间的话,就会发生上一个任务未执行完毕,下一个任务又开始执行的逻辑,这种也是有风险的。所以最好使用多线程方式,自己控制线程池的数量,线程名称等。

二、使用多线程

需要实现SchedulingConfigurer接口,然后自定义线程池,这样凡是用到@Scheduled注解的都可以用该线程池,同时也解决了上述比较坑的两个问题。

@Configuration
@EnableScheduling
public class ScheduleConfig implements SchedulingConfigurer {
    @Override
    public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {
        taskRegistrar.setScheduler(taskExecutor());
    }
    @Bean
    public Executor taskExecutor() {
        return Executors.newScheduledThreadPool(20, (Runnable r) -> {
            Thread thread = new Thread(r);
            thread.setName("自定义线程名称");
            return thread;
        });
    }
}

以上这一行

thread.setName(“自定义线程名称”);

是设置线程名称,可以通过Thread.currentThread().getName()拿到该名称,便于在日志中进行排查问题。

小结一下

集群版本如果要使用@Scheduled的话,需要加分布式锁来控制,或者直接用分布式定时任务Elasticjob或者xxl-job等。

以上为个人经验,希望能给大家一个参考,也希望大家多多支持我们。

(0)

相关推荐

  • 深入剖析springBoot中的@Scheduled执行原理

    目录 springBoot @Scheduled执行原理 一.前言 二.@Scheduled使用方式 三.@Scheduled代码执行原理说明 @Scheduled 的一些坑 springBoot @Scheduled执行原理 一.前言 本文主要介绍Spring Boot中使用定时任务的执行原理. 二.@Scheduled使用方式 定时任务注解为@Scheduled.使用方式举例如下: //定义一个按时间执行的定时任务,在每天16:00执行一次. @Scheduled(cron = "0 0 1

  • springboot定时任务@Scheduled执行多次的问题

    目录 springboot定时任务@Scheduled执行多次 原因 解决方法 使用 @Scheduled 定时任务突然不执行了 springboot定时任务@Scheduled执行多次 在spring boot开发定时任务时遇到一个很怪异的现象..我进行调试模式,在没有bug的情况下.执行了三 次才停止..如图: 原因 是因为执行时间太短,在CronSequenceGenerator.class的next方法. public Date next(Date date) { Calendar ca

  • springboot 定时任务@Scheduled实现解析

    这篇文章主要介绍了springboot 定时任务@Scheduled实现解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 1.pom.xml中导入必要的依赖: <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version&g

  • SpringBoot项目中使用@Scheduled读取动态参数

    目录 使用@Scheduled读取动态参数 1.基于@Scheduled可配置开发 2.基于代码实现 spring boot Scheduled动态配置 使用@Scheduled读取动态参数 1.基于@Scheduled可配置开发 application.propertites: read.timer.parmas=0 0/1 * * * * 定时类: @Component public class ScheduledService { Logger logger= LoggerFactory.

  • 聊聊SpringBoot的@Scheduled的并发问题

    目录 SpringBoot @Scheduled的并发 spring @Scheduled 并发执行 SpringBoot @Scheduled的并发 由于SpringBoot自带的@Scheduled是一个阻塞执行的定时任务,所以效率会很慢,就会造成同一个时间段内只有一个定时任务在执行,其余的就会阻塞 现有两个定时任务 @Component("aa") public class aa { @Scheduled(cron = "0 44 17 * * ?") pub

  • SpringBoot中使用@Scheduled注解创建定时任务的实现

    在项目日常开发过程中,经常需要定时任务来帮我们做一些工作,如清理日志.定时任务的实现方法主要有 Timer.Quartz 以及 elastic-job Timer 实现定时任务 只执行一次的定时任务 Timer timer = new Timer(); timer.schedule(new TimerTask() { @Override public void run() { System.out.println("2000毫米后执行一次."); } }, 2000); timer.s

  • SpringBoot执行定时任务@Scheduled的方法

    在做项目时,需要一个定时任务来接收数据存入数据库,后端再写一个接口来提供该该数据的最新的那一条. 数据保持最新:设计字段sign的值(0,1)来设定是否最新 定时任务插入数据:首先进行更新,将所有为1即新数据设置过期,然后插入新数据,设置sign为1.这两个操作是原子操作.通过添加事务来进行控制. Java 定时任务的几种实现方式 基于 java.util.Timer 定时器,实现类似闹钟的定时任务 使用 Quartz.elastic-job.xxl-job 等开源第三方定时任务框架,适合分布式

  • 使用springboot时,解决@Scheduled定时器遇到的问题

    目录 @Scheduled定时器遇到的问题 下面说一下@Scheduled 注解的几个参数 一.可以通过配置文件配置进来的 二.不可通过配置文件配置的 (作用相同) 定时任务@Scheduled使用的那些坑 一.使用的那些坑? 1.单线程 2.@Async和@EnableAsync 二.使用多线程 小结一下 @Scheduled定时器遇到的问题 @Scheduled 这个注解确实给我们带了很大的方便,我们只要加上该注解,并且根据需求设置好就可以使用定时任务了. 但是,我们需要注意的是,@Sche

  • 解决SpringBoot中的Scheduled单线程执行问题

    目录 问题描述 原因分析: 解决方案: 补充: 问题描述 在一次SpringBoot中使用Scheduled定时任务时,发现某一个任务出现执行占用大量资源,会导致其他任务也执行失败.类似于以下模拟场景,test1定时任务模拟有五秒钟执行时间,这时会同步影响到test2任务的执行,导致test2任务也变成五秒执行一次. @Scheduled(fixedRate = 1000) public void test1() throws InterruptedException { log.info(Th

  • springboot schedule 解决定时任务不执行的问题

    @schedule 注解 是springboot 常用的定时任务注解,使用起来简单方便,但是如果定时任务非常多,或者有的任务很耗时,会影响到其他定时任务的执行,因为schedule 默认是单线程的,一个任务在执行时,其他任务是不能执行的.解决办法是重新配置schedule,改为多线程执行.只需要增加下面的配置类就可以了. import org.springframework.boot.autoconfigure.batch.BatchProperties; import org.springfr

  • vue离开页面时如何销毁定时器

    目录 vue离开页面销毁定时器 组件里定时器销毁问题 解决方法1 解决方案2 vue离开页面销毁定时器 beforeDestroy() { if(this.timer) { clearInterval(this.timer); //关闭  }  //利用vue的生命周期函数 vue 是单页面应用,路由切换后,定时器并不会自动关闭,需要手动清除,当页面被销毁时,清除定时器即可. 组件里定时器销毁问题 我在a页面写一个定时,让他每秒钟打印一个1,然后跳转到b页面,此时可以看到,定时器依然在执行.这样

  • SpringBoot中使用@scheduled定时执行任务的坑

    目录 解决办法 1.将@Scheduled注释的方法内部改成异步执行 2.把Scheduled配置成成多线程执行 要注意什么坑 不绕弯子了,直接说这个坑是啥: SpringBoot使用@scheduled定时执行任务的时候是在一个单线程中,如果有多个任务,其中一个任务执行时间过长,则有可能会导致其他后续任务被阻塞直到该任务执行完成.也就是会造成一些任务无法定时执行的错觉 可以通过如下代码进行测试:     @Scheduled(cron = "0/1 * * * * ? ")    

  • 轻松解决JavaScript定时器越走越快的问题

    解决JavaScript定时器越走越快的问题 之前在项目中写了定时器来做循环播放,但是总是会有越走越快的问题,开始是以为前后的HTML代码拼接的有问题,时间紧急的情况下反复改了很多也没什么效果,后来发现是js定时器的问题,在这里记录一下. (setinterval)多次初始化 使用js定时器(setinterval)首要的问题就是要记得清除,即调用(clearInterval)方法,由于没有使用定时器的经验,我一开始是没有清除定时器,程序每一次初始化的时候都调用一次定时器,之前的定时器实例没有被

  • jQuery Ajax async=>false异步改为同步时,解决导致浏览器假死的问题

    今天做一个需求遇到了这么个情况,就是用户个人中心有个功能,点击按钮,可以刷新用户当前的积分,这个肯定需要使用到ajax的同步请求了,当时喀喀喀三下五除二写玩了,大概代码如下: /** * 异步当前用户积分 by zgw 20161216 * @return {[type]} [description] */ function flushIntegralSum() { //点击按钮刷新前修改按钮的文案,已经去掉点击事情,防止多次点击 $("#flushbutton").replaceWi

  • SpringBoot服务器端解决跨域问题

    本文导航 SpringBoot解决跨域问题的两种方案: 1.通过给方法或者类加注解的形式,@CrossOrigin. 2.继承接口,重写addCorsMappings方法. 第一种方式: @RestController @CrossOrigin("http://localhost:8081") public class BaseController { @GetMapping("/hello") public String testGet(){ return &qu

随机推荐