专栏首页每日分享java架构小知识Spring4定时器 cronTrigger和simpleTrigger实现方法

Spring4定时器 cronTrigger和simpleTrigger实现方法

spring4定时器 cronTrigger和simpleTrigger实现方法

Quartz 是个开源的作业调度框架,为在 Java 应用程序中进行作业调度提供了简单却强大的机制。Quartz 允许开发人员根据时间间隔(或天)来调度作业。它实现了作业和触发器的多对多关系,还能把多个作业与不同的触发器关联。整合了 Quartz 的应用程序可以重用来自不同事件的作业,还可以为一个事件组合多个作业。

SimpleTrigger 当需要在规定的时间执行一次或在规定的时间段以一定的时间间隔重复触发执行Job时,SimpleTrigger就可以满足要求;SimpleTrigger的属性有:开始时间、结束时间、重复次数和重复的时间间隔,重复次数属性的值可以为0、正整数、或常量 SimpleTrigger.REPEAT_INDEFINITELY,重复的时间间隔属性值必须为0或长整型的正整数,以毫秒作为时间单位,当重复的时 间间隔为0时,意味着与Trigger同时触发执行(或几乎与Scheduler开始时同时触发执行)。如果有指定结束时间属性值,则结束时间属性优先于重复次数属性,这样的好处在于:当我们需要创建一个每间隔10秒钟触发一次直到指定的结束时间的 Trigger,而无需去计算从开始到结束的所重复的次数,我们只需简单的指定结束时间和使用REPEAT_INDEFINITELY作为重复次数的属性 值即可(我们也可以指定一个比在指定结束时间到达时实际执行次数大的重复次数)。

CronTrigger 支持比 SimpleTrigger 更具体的调度,而且也不是很复杂。基于 cron 表达式,CronTrigger 支持类似日历的重复间隔,而不是单一的时间间隔。

Cron 表达式包括以下 7 个字段

格式: [秒] [分] [小时] [日] [月] [周] [年] 序号 说明 是否必填 允许填写的值 允许的通配符 1 秒 是 0-59 , - * / 2 分 是 0-59 , - * / 3 小时 是 0-23 , - * / 4 日 是 1-31 , - * ? / L W 5 月 是 1-12 or JAN-DEC , - * / 6 周 是 1-7 or SUN-SAT , - * ? / L # 7 年 否 empty 或 1970-2099 , - * /

Quartz官方网站对SimpleTrigger和CronTrigger的简单对比: SimpleTrigger is handy if you need 'one-shot' execution (just single execution of a job at a given moment in time), or if you need to fire a job at a given time, and have it repeat N times, with a delay of T between executions.当你需要的是一次性的调度(仅是安排单独的任务在指定的时间及时执行),或者你需要在指定的时间激活某个任务并执行N次,设置每次任务执行的间隔时间T。那此时使用SimpleTrigger将是非常方便的。

CronTrigger is useful if you wish to have triggering based on calendar-like schedules - such as "every Friday, at noon" or "at 10:15 on the 10th day of every month."如果你需要安排的任务时基于日期的-比如"每个星期五正午"或者"每个月10号的10:15",使用CronTrigger将是非常有用的。

1、配置applicationcontext.xml

<!-- cronTrigger实现方式 -->
<bean name="exampleJob" class="org.springframework.scheduling.quartz.JobDetailBean">
        <property name="jobClass" value="com.ouku.entities.report.ReportTimerTask" />
        <property name="jobDataAsMap">
            <map>
                <entry key="timeout" value="3600" />
            </map>
        </property>
    </bean>
    <bean id="springUtil" class="com.ouku.util.SpringUtil" />
    <bean id="cronTrigger"
        class="org.springframework.scheduling.quartz.CronTriggerFactoryBean">
        <property name="jobDetail" ref="exampleJob" />
        <!-- run every morning at 6 AM -->
        <!-- <property name="cronExpression" value="0 0 6 * * ?" /> -->
       <!-- <property name="cronExpression" value="0 0/1 * * * ?" /> --><!-- 每分钟 -->
        <property name="cronExpression" value="0/5 * * * * ?" /> <!-- 每秒 -->
    </bean>

    <bean id="exampleBusinessObject" class="com.ouku.entities.report.ReportTimerTaskTwo" />
    <bean id="jobDetail"
<!-- simpleTrigger实现方式 -->
class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">
        <property name="targetObject" ref="exampleBusinessObject" />
        <property name="targetMethod" value="doIt" />
        <property name="concurrent" value="false" />
    </bean>
    <bean id="simpleTrigger"
          class="org.springframework.scheduling.quartz.SimpleTriggerFactoryBean">
        <!-- see the example of method invoking job above -->
        <property name="jobDetail" ref="jobDetail" />
        <!-- 0 seconds -->
        <property name="startDelay" value="0" />
        <!-- repeat every 5 seconds -->
        <property name="repeatInterval" value="5000" />
    </bean>

    <!-- 总调度用于启动Spring定时器 -->
    <bean class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
        <property name="triggers">
            <list>
                <ref bean="cronTrigger" />
                <ref bean="simpleTrigger"/>
            </list>
        </property>
    </bean>

其中<property name="concurrent" value="false" />

  1. 设置为false时,定时任务会串行执行;就是定时任务开启时,知道这个job结束,才会执行下一个定时任务;
  2. 设置为true时,定时任务会并发执行,就是不管这个job有没有执行完,定时任务都会启动,如果没有执行完,定时任务会开一个新的线程来执行job,确保能在设定的时间间隔内执行job;定时器默认最多有十个线程,当十个线程都用完时,定时任务会阻塞,直到有新的线程可用,才会开启定时任务去执行job;

2.利用cronTrigger的Java实现

package com.ouku.entities.report;

import java.util.Date;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.springframework.scheduling.quartz.QuartzJobBean;
import com.ouku.report.ReportTask;

public class ReportTimerTask extends QuartzJobBean  {
    private int timeout;



    public void setTimeout(int timeout) {
        this.timeout = timeout;
    }

    @Override
    protected void executeInternal(JobExecutionContext arg0)
            throws JobExecutionException {
        try {
            Date date = new Date();
            String dd = " " + date.getMinutes() + ":" + date.getSeconds() + " ";
            System.out.println("AAA" + dd);
            //to do
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

}

3.利用simpleTrigger的Java实现

package com.ouku.entities.report;

import java.util.Date;

import org.quartz.JobExecutionException;
import com.ouku.report.ReportTask;

public class ReportTimerTaskTwo {

    public void doIt() throws JobExecutionException {
        try {
            Date date = new Date();
            String dd = " " + date.getMinutes() + ":" + date.getSeconds() + " ";
            System.out.println("sss1" + dd);
            //to do ..
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

}

在使用并发的情况下,当Job执行时间超过间隔时间时,调度框架为了能让任务按照我们预定的时间间隔执行,会马上启用新的线程执行任务

再次强调,spring4 quartz最多可以为我们开启十个线程,当我们需要执行的任务有锁的情况下,那么在十个线程用完之后,定时器没有线程可以开启,这时候就会出现定时任务的时间间隔超过我们设定的时间间隔;

我们怎么解决这个情况呢?

一、优化我们执行的job,使其在设定的时间间隔内执行完;

二、设置时间间隔更长一点;

我们再来看看串行执行和并发执行的区别:

下面是串行执行时,每个线程的执行情况:

我们可以看到,每个定时任务是在job完成之后才会开启新的线程来执行下一个job;

下面看看并发执行,每个线程执行的情况:

我们可以看到,定时任务是按照我们设置的时间间隔执行的,不会在意job是否执行完,如果没有执行完,定时任务会开启一个新的线程来执行job;

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • IDEA建立Spring MVC Hello World 详细入门教程

    作为.NET转Java的码农,有时候真的很怀念宇宙第一IDE:Visual Studio,根据模板创建的项目很少有不能直接运行的,算了,不说也罢,继续配置。。。

    会说话的丶猫
  • Tomcat远程调试

    本文环境:tomcat:apache-tomcat-8.5.6,eclipse:eclipse-jee-oxygen

    会说话的丶猫
  • Controller 层中,到底是 返回界面 还是JSON?

    会说话的丶猫
  • 这些linux、docker、k8s的命令,你知道多少呢

    2、cd --切换目录(cd 有很多种用法,但是刚接触linux人的来说只要记住这个就可以了,剩下的以后慢慢学,如cd ..,cd -,cd ~,cd ....

    格姗知识圈
  • Spring学习(二)bean的循环依赖

    使用spring bean的循环依赖在我们开发中是很普遍的,并且spring容器中也默认支持循环依赖。以下为一个简单的bean的循环依赖示例:

    虞大大
  • Python从入门到摔门(5):18式优雅你的Python

    在cmd中输入jupyter notebook --generate-config,然后找到生成的配置文件jupyter_notebook_config.py,...

    Python之道
  • Quartz组件使用二 原

    南郭先生
  • matplotlib 3D 绘图(一)

    用户6021899
  • Linux-grep 命令和find 命令 (6)

    grep与find区别: grep:查找指定目录下过滤文本文件中行数据 find:查找指定目录下文件  grep使用 格式:   grep "text"   *...

    张诺谦
  • 纷享销客罗旭:SaaS 公司的战略思考与探讨|腾讯SaaS加速器·CEO说

    ? 来源:牛透社  作者:罗旭  编辑 :霜雪 ---- SaaS 在国内发展多年,大部分企业还处于快速成长前的摸索期。本文是罗旭结合「纷享销客」多年的经验...

    腾讯SaaS加速器

扫码关注云+社区

领取腾讯云代金券