在项目中使用定时任务,如何避免在当前任务因阻塞,还没有结束时,定时时间到了,另外一个定时任务又进入执行?

定时任务的实现方式

  • 1、Timer:这是java自带的java.util.Timer类,这个类允许你调度一个java.util.TimerTask任务。使用这种方式可以让你的程序按照某一个频度执行,但不能在指定时间运行。一般用的较少。
  • 2、ScheduledExecutorService:也jdk自带的一个类;是基于线程池设计的定时任务类,每个调度任务都会分配到线程池中的一个线程去执行,也就是说,任务是并发执行,互不影响。
  • 3、Spring Task:Spring3.0以后自带的task,可以将它看成一个轻量级的Quartz,而且使用起来比Quartz简单许多。
  • 4、Quartz:这是一个功能比较强大的的调度器,可以让你的程序在指定时间执行,也可以按照某一个频度执行,配置起来稍显复杂

本文参考链接:https://www.jianshu.com/p/b6809b5a0c26

Spring Task的使用

@Component
@EnableScheduling
//@Async
public class OrderTask {

    /**默认是fixedDelay 上一次执行完毕时间后执行下一轮*/
    @Scheduled(cron = "0/5 * * * * *")
    public void run() throws InterruptedException {
        System.out.println(Thread.currentThread().getName()+"使用cron  {}开始"+(LocalDateTime.now()));
        Thread.sleep(6000);
        System.out.println(Thread.currentThread().getName()+"=====>>>>>使用cron  {}"+(LocalDateTime.now()));
    }

    /**fixedRate:上一次开始执行时间点之后5秒再执行*/
    @Scheduled(fixedRate = 5000)
    public void run1() throws InterruptedException {
        System.out.println(Thread.currentThread().getName()+"使用fixedRate  {}开始"+(LocalDateTime.now()));
        Thread.sleep(6000);
        System.out.println(Thread.currentThread().getName()+"=====>>>>>使用fixedRate  {}"+(LocalDateTime.now()));
    }

    /**fixedDelay:上一次执行完毕时间点之后5秒再执行*/
    @Scheduled(fixedDelay = 5000)
    public void run2() throws InterruptedException {
        System.out.println(Thread.currentThread().getName()+"使用fixedDelay  {}开始"+(LocalDateTime.now()));

        Thread.sleep(60*1000);
        System.out.println(Thread.currentThread().getName()+"=====>>>>>使用fixedDelay  {}"+(LocalDateTime.now()));
    }

    /**第一次延迟2秒后执行,之后按fixedDelay的规则每5秒执行一次*/
    @Scheduled(initialDelay = 2000, fixedDelay = 5000)
    public void run3() throws InterruptedException {
        System.out.println(Thread.currentThread().getName()+"使用initialDelay  {}开始"+(LocalDateTime.now()));
        Thread.sleep(7000);
        System.out.println(Thread.currentThread().getName()+"=====>>>>>使用initialDelay  {}"+(LocalDateTime.now()));
    }
}

** 不使用异步时,执行如下:**

使用异步:

@Configuration
@EnableAsync
public class AsyncConfig {

    private int corePoolSize = 10;
    private int maxPoolSize = 200;
    private int queueCapacity = 10;
    @Bean
    public Executor taskExecutor() {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        executor.setCorePoolSize(corePoolSize);
        executor.setMaxPoolSize(maxPoolSize);
        executor.setQueueCapacity(queueCapacity);
        executor.initialize();
        return executor;
    }
}

在类上或者方法上【不】使用注解@Async

执行如下:

scheduling-1=====>>>>>使用fixedDelay  {}2020-04-22T20:32:58.420
scheduling-1使用initialDelay  {}开始2020-04-22T20:32:58.420
scheduling-1=====>>>>>使用initialDelay  {}2020-04-22T20:33:05.421
scheduling-1使用cron  {}开始2020-04-22T20:33:05.421
scheduling-1=====>>>>>使用cron  {}2020-04-22T20:33:11.426
scheduling-1使用fixedRate  {}开始2020-04-22T20:33:11.426
scheduling-1=====>>>>>使用fixedRate  {}2020-04-22T20:33:17.429
scheduling-1使用fixedRate  {}开始2020-04-22T20:33:17.429
scheduling-1=====>>>>>使用fixedRate  {}2020-04-22T20:33:23.433
scheduling-1使用fixedRate  {}开始2020-04-22T20:33:23.433
scheduling-1=====>>>>>使用fixedRate  {}2020-04-22T20:33:29.437
scheduling-1使用fixedRate  {}开始2020-04-22T20:33:29.437
scheduling-1=====>>>>>使用fixedRate  {}2020-04-22T20:33:35.442
scheduling-1使用fixedRate  {}开始2020-04-22T20:33:35.442
scheduling-1=====>>>>>使用fixedRate  {}2020-04-22T20:33:41.444
scheduling-1使用fixedRate  {}开始2020-04-22T20:33:41.445
scheduling-1=====>>>>>使用fixedRate  {}2020-04-22T20:33:47.445
  • 由上可知,只有一个线程在执行;
  • fixedDelay的特点,每个任务执行完之后,再隔5秒,才会继续执行;
  • fixedRate的特点,每隔5秒之后,就会执行执行,不会等待上个任务执行完成;

在类上或者方法上使用注解@Async
**执行如下: **

taskExecutor-5使用fixedRate  {}开始2020-04-22T20:44:27.622
taskExecutor-6使用fixedDelay  {}开始2020-04-22T20:44:27.623
taskExecutor-7使用initialDelay  {}开始2020-04-22T20:44:29.623
taskExecutor-2=====>>>>>使用fixedDelay  {}2020-04-22T20:44:29.628
taskExecutor-8使用cron  {}开始2020-04-22T20:44:30.003
taskExecutor-4=====>>>>>使用cron  {}2020-04-22T20:44:31.006
taskExecutor-3=====>>>>>使用initialDelay  {}2020-04-22T20:44:31.626
taskExecutor-9使用fixedRate  {}开始2020-04-22T20:44:32.624
taskExecutor-10使用fixedDelay  {}开始2020-04-22T20:44:32.624
taskExecutor-6=====>>>>>使用fixedDelay  {}2020-04-22T20:44:34.624
taskExecutor-2使用initialDelay  {}开始2020-04-22T20:44:34.624
taskExecutor-4使用cron  {}开始2020-04-22T20:44:35
taskExecutor-8=====>>>>>使用cron  {}2020-04-22T20:44:36.008
taskExecutor-7=====>>>>>使用initialDelay  {}2020-04-22T20:44:36.624
taskExecutor-3使用fixedRate  {}开始2020-04-22T20:44:37.620
taskExecutor-6使用fixedDelay  {}开始2020-04-22T20:44:37.625
taskExecutor-10=====>>>>>使用fixedDelay  {}2020-04-22T20:44:39.627
taskExecutor-8使用initialDelay  {}开始2020-04-22T20:44:39.627
taskExecutor-7使用cron  {}开始2020-04-22T20:44:40.005
taskExecutor-4=====>>>>>使用cron  {}2020-04-22T20:44:41.005
taskExecutor-2=====>>>>>使用initialDelay  {}2020-04-22T20:44:41.627
taskExecutor-10使用fixedRate  {}开始2020-04-22T20:44:42.622
taskExecutor-4使用fixedDelay  {}开始2020-04-22T20:44:42.626
taskExecutor-6=====>>>>>使用fixedDelay  {}2020-04-22T20:44:44.628
taskExecutor-2使用initialDelay  {}开始2020-04-22T20:44:44.631
taskExecutor-6使用cron  {}开始2020-04-22T20:44:45.005
taskExecutor-7=====>>>>>使用cron  {}2020-04-22T20:44:46.006
taskExecutor-8=====>>>>>使用initialDelay  {}2020-04-22T20:44:46.633

总结

如果想要一个任务没有执行完时,下一个定时任务等待,则可以使用fixedDelay, 延时定时器;但是,如果你用了异步,多线程的方式,则fixedDelay会失效。所以,你可以在你必须要等待上一次任务执行才进行下一步操作的定时任务,则可以选择单线程环境下的fixedDelay。

  • 3
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值