• spring @Scheduled 并发


    一.spring定时任务配置

    applicationContext.xml:红色代码部分为需要配置的部分。

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop"
       xmlns:p="http://www.springframework.org/schema/p" xmlns:tx="http://www.springframework.org/schema/tx"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:task="http://www.springframework.org/schema/task"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
    http://www.springframework.org/schema/tx
    http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
    http://www.springframework.org/schema/aop
    http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
    http://www.springframework.org/schema/task
    http://www.springframework.org/schema/task/spring-task-3.1.xsd
    http://www.springframework.org/schema/context
    http://www.springframework.org/schema/context/spring-context-3.0.xsd">
       <!--   定时器配置   -->
       <task:annotation-driven/>
       <task:scheduler id="myScheduler" pool-size="5"/>
    

      

    注意事项:<task:scheduler id="myScheduler" pool-size="5"/>这段配置为非必须,配置这段的原因是spring定时任务默认是单线程的。配置了这段表示不同定时任务不论是否在同一时间点执行,任务之间互不影响(即多线程执行)。但是自己还是会影响自己。下面介绍具体问题以及解决方式。

    二.测试1(不加<task:scheduler id="myScheduler" pool-size="5"/>)
    方法代码:

    public class QuartzServiceImpl implements QuartzService {
    
    
        //1.简易定时器-(每10秒执行一次,执行时间为20秒)
        @Scheduled(cron = "0/10 * *  * * ? ")
        public void taskA() {
            try {
                System.out.println(DateUtils.forMatDate(new Date())+"||A任务每10秒执行一次..");
                Thread.sleep(20*1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    
        //2.简易定时器-每5秒执行一次
        @Scheduled(cron="0/5 * *  * * ? ")
        public void taskB(){
            System.err.println(DateUtils.forMatDate(new Date())+"||B任务每5秒执行一次进入测试");
        }
    
    }
    

      

    结果:很明显A任务和B任务会相互影响。B任务正常应该是从15秒到20秒,但是20秒的时候执行了A任务(A任务又执行了20秒),因此B任务在40秒的时候再次执行。

    二.测试2(加<task:scheduler id="myScheduler" pool-size="5"/>)
    方法代码:同上,这次加上了<task:scheduler id="myScheduler" pool-size="5"/>这段配置

    结果:上面的配置将spirng定时任务变为多线程,因此任务之间不会相互影响了。很明显A任务不再影响B任务的执行。正常的按每隔5秒钟执行一次。但是A任务是10秒钟执行一次,按理说应该41分30秒的时候执行了一次,下一次执行应该是40秒,而这里却变为了40分00秒的执行才执行。并没有按照每隔10秒钟执行一次。这也是上面我提到的加了线程池之后自己任务的执行时间会影响自己的下次执行。

    三.测试3(加@Async注解)
    方法代码:两个方法上面分别加了 @Async注解-即异步执行

    public class QuartzServiceImpl implements QuartzService {
    
    
        //1.简易定时器-(每10秒执行一次,执行时间为20秒)
        @Scheduled(cron = "0/10 * *  * * ? ")
        @Async
        public void taskA() {
            try {
                System.out.println(DateUtils.forMatDate(new Date())+"||A任务每10秒执行一次..");
                Thread.sleep(20*1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    
        //2.简易定时器-每5秒执行一次
        @Scheduled(cron="0/5 * *  * * ? ")
        @Async
        public void taskB(){
            System.err.println(DateUtils.forMatDate(new Date())+"||B任务每5秒执行一次进入测试");
        }
    

      

    结果:结果A任务和B任务都不会影响,并且自己也不会因为自己的执行时间过长而影响自己。

    A任务每10秒正常执行一次。B任务每5秒正常执行一次。

    四.总结
    1.简单使用定时任务测试一即可。

    2.解决并发使用测试二或测试三即可(建议使用测试二)。

    原因,如果你的代码真的出现了测试三的情况,即本任务的执行时间影响了本任务的下次执行,那么你应该优化你的代码,sql语句等。而不是,让程序一直"欠费"的执行下去。

  • 相关阅读:
    十二周学习进度
    冲刺第十天
    19.Maven 的单模块之 Spring MVC + Spring + Spring Data JPA 项目(基于 IntelliJ IDEA)
    18. Maven 的单模块 / 多模块之 Spring MVC + Spring + Mybatis 项目讲解(重点)
    16.Java Web 项目环境搭建
    17.Maven 项目介绍
    15.Postfix Completion 的使用
    16.插件讲解
    14.Emmet 讲解
    13.文件代码模板讲解
  • 原文地址:https://www.cnblogs.com/jtlgb/p/10564622.html
Copyright © 2020-2023  润新知