Spring @Scheduled @Async联合实现调度任务

Posted 蓝萝卜blu

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Spring @Scheduled @Async联合实现调度任务相关的知识,希望对你有一定的参考价值。

定时任务之前一直用的是quartz之类,但是注意到Spring中其实也提供了一种简单的调度注释@Scheduled,也就想尝一下鲜..

代码示意如下:

@Component
@EnableScheduling
public class AsyncTaskHandlerTask {

    @Scheduled(fixedDelay = 1000)
    public void task1() {
         //输出日志
    }

    @Scheduled(fixedDelay = 1000)
    public void task2() {
         //输出日志    
    }
}

执行了一下,完全ok,日志打印正常,2个任务也都正常定时执行了.那好,添加些业务逻辑进去:

@Component
@EnableScheduling
public class AsyncTaskHandlerTask {

    @Scheduled(fixedDelay = 1000)
    public void task1() {
         while(true){
            ....
         }
    }

    @Scheduled(fixedDelay = 1000)
    public void task2() {
         while(true){
            ....
         }
     }

}

再启动,咦,奇怪了,怎么定时任务没有执行呢?倘使我之前没有输出日志试验,我可能就认为注解的用法错了呢...重新添加日志,下断点重跟了一下启动过程发现:

程序进入到while死循环后就卡死了,没有再继续启动另一个定时任务了.通过现象可知@Scheduled启动过程是一个单线程同步启动过程,故一旦中途被阻塞,会导致整个启动过程阻塞,

其余的定时任务都不会启动.这明显很奇怪,网上的教程大多数是xml配置形式,Spring的官网我这头打开又奇慢无比..但是从xml的配置形式可知需要配置一个线程池来启动定时任

务.但是Javaconfig形式的则没有说明.但是我查询到了另一个注解@Async,这个异步注解我是使用过的,可以指定线程池,打到方法上后便会以指定的线程池来执行方法.然后解决方案来了:

@Component
@EnableScheduling
public class AsyncTaskHandlerTask {

    @Scheduled(fixedDelay = 1000)
    @Async
    public void task1() {
         while(true){
            ....
         }
    }

    @Scheduled(fixedDelay = 1000)
    @Async
    public void task2() {
         while(true){
            ....
         }
     }

}

再次启动,不会再被阻塞.

以上是关于Spring @Scheduled @Async联合实现调度任务的主要内容,如果未能解决你的问题,请参考以下文章

spring @Scheduled定时任务使用说明及基本工作原理介绍

@Async 与 @Scheduled

Spring中@Async和FixedDelay共同使用

Spring @Scheduled 使用详解

spring的@scheduled定时怎么加返回值

Spring Boot整合@Scheduled定时计划