定时任务实现方法总结与分析

原创 2016年06月01日 17:37:40

上次熟悉了MarkDown的用法之后,由于各种原因一直没有时间更新博客。。。这次打算把我之前总结的一些东西陆陆续续的写在博客里,希望下次用到的时候能够快速记起来~

—————————————华丽的分割线——————————————–

1 定时任务简介

在应用开发中,经常需要一些周期性的操作,如:需要在每天凌晨时候分析一次前一天的日志信息、需要每隔5分钟检查一下某个模块是否有异常然后自动发送邮件给管理员,在项目运行到第30天的时候需要执行某些操作等等。这些功能需求就需要我们使用一些定时任务方法去实现,本文将介绍目前J2EE项目常用的几种定时任务方法并比较它们的优缺点。

2 J2EE项目中常用到的三种定时任务实现方法

2.1 java.util.Timer类

2.1.1 简介

先来介绍下Java自带的java.util.Timer类,这个类允许你调度一个java.util.TimerTask任务。使用这种方式可以让你的程序按照某一个频度执行,但不能在指定时间运行。TimerTask类用于实现由Timer安排的一次或重复执行的某个任务。每一个Timer对象对应的是一个线程,因此计时器所执行的任务应该迅速完成,否则会延迟后续的任务执行。

java.util.Timer类方法摘要

void cancel()
终止此计时器,丢弃所有当前已安排的任务。
int purge()
从此计时器的任务队列中移除所有已取消的任务。
void schedule(TimerTask task, Date time)
安排在指定的时间执行指定的任务。
void schedule(TimerTask task, Date firstTime, long period)
安排指定的任务在指定的时间开始进行重复的固定延迟执行。
void schedule(TimerTask task, long delay)
安排在指定延迟后执行指定的任务。
void schedule(TimerTask task, long delay, long period)
安排指定的任务从指定的延迟后开始进行重复的固定延迟执行。
void scheduleAtFixedRate(TimerTask task, Date firstTime, long period)
安排指定的任务在指定的时间开始进行重复的固定速率执行。
void scheduleAtFixedRate(TimerTask task, long delay, long period)
安排指定的任务在指定的延迟后开始进行重复的固定速率执行。

TimerTask类方法摘要

boolean cancel()
取消此计时器任务。
abstract void run()
此计时器任务要执行的操作。
long scheduledExecutionTime()
返回此任务最近实际执行的安排执行时间。

2.1.2 使用方法

使用Timer类的schedule(TimerTask task, long delay, long period)方法启动定时器。

    Timer  timer=new Timer();  
    MyTask myTask=new MyTask();  
    timer.schedule(myTask, 1000, 2000); 

TimerTask类主要实现run()方法里的业务逻辑,用法如下:

import java.text.SimpleDateFormat;  
import java.util.Date;  
import java.util.TimerTask;  

public class MyTask extends TimerTask {  

    @Override  
    public void run() {  
        // TODO Auto-generated method stub  
        SimpleDateFormat simpleDateFormat=null;  
        simpleDateFormat=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss:SSS");  
        System.out.println("当前的系统时间为:"+simpleDateFormat.format(new Date()));  

    }  
}

2.1.3 扩展内容(往定时任务方法中传参数)

import java.text.SimpleDateFormat;  
import java.util.Date;  
import java.util.TimerTask;  

public class WaitListTimerTask extends TimerTask {  
private WaitList waitList;
public WaitListTimerTask(WaitList waitList){
        this.waitList=waitList;
}

    @Override  
    public void run() {  
        // 参数waitList使用示例  
        List<CourseWaitList> allCourseWaitList = this.waitList.getAllCourseWaitList();

    }  
}

2.2 Spring3.0以后自带的Spring-task

2.2.1 简介

Spring3.0以后自主开发了定时任务工具spring task,可以将它比作一个轻量级的Quartz,而且使用起来很简单,除spring相关的包外不需要额外的包,而且支持注解和配置文件两种形式,下面将分别介绍这两种方式。

2.2.2 使用方法

第一种:配置文件方式
①编写作业类
即普通的pojo,如下:

import org.springframework.stereotype.Service;  

@Service  
public class TaskJob {  
    public void job1() {  

        System.out.println(“任务进行中。。。”);  

    }  
}

②在spring配置文件头中添加命名空间及描述

<beans xmlns="http://www.springframework.org/schema/beans"  

    xmlns:task="http://www.springframework.org/schema/task"   

    …… 

    xsi:schemaLocation="http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task-3.0.xsd">

③Spring配置文件中设置具体的任务

<task:scheduled-tasks>   

        <task:scheduled ref="taskJob" method="job1" cron="0 * * * * ?"/>   

</task:scheduled-tasks>  
<context:component-scan base-package=" com.gy.mytask " />

说明:ref参数指定的即任务类,method指定的即需要运行的方法,croncronExpression表达式,具体写法这里不介绍了,详情见附录。
这个配置根据项目实际情况调整包的位置,spring扫描注解用的。

第二种:使用注解形式
①编写作业类
即普通的pojo,如下:

import org.springframework.scheduling.annotation.Scheduled;    
import org.springframework.stereotype.Component;  



@Component(“taskJob”)  

public class TaskJob {  

    @Scheduled(cron = "0 0 3 * * ?")  

    public void job1() {  

        System.out.println(“任务进行中。。。”);  

    }  

}  

注意:此处@Schedule注解有三个方法或者叫参数,分别表示的意思是:
cron:指定cron表达式
fixedDelay:即表示从上一个任务完成开始到下一个任务开始的间隔,单位是毫秒。
fixedRate:即从上一个任务开始到下一个任务开始的间隔,单位是毫秒。

②添加task相关的配置

<?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:context="http://www.springframework.org/schema/context"  
    xmlns:tx="http://www.springframework.org/schema/tx"  
    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/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd  
        http://www.springframework.org/schema/context   
http://www.springframework.org/schema/jdbc/spring-jdbc-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/task http://www.springframework.org/schema/task/spring-task-3.0.xsd"  
    default-lazy-init="false">  

    <context:annotation-config />  

    <!—spring扫描注解的配置   -->  
<context:component-scan base-package="com.gy.mytask" />  

<!—开启这个配置,spring才能识别@Scheduled注解   -->  
    <task:annotation-driven scheduler="qbScheduler" mode="proxy"/>  

    <task:scheduler id="qbScheduler" pool-size="10"/>  

说明:理论上只需要加上《task:annotation-driven /》这句配置就可以了,这些参数都不是必须的。

2.3 定时任务框架Quartz

2.3.1 简介

Quartz是OpenSymphony开源组织在Job scheduling领域又一个开源项目,它可以与J2EE与J2SE应用程序相结合也可以单独使用。Quartz可以用来创建简单或为运行十个,百个,甚至是好几万个Jobs这样复杂的程序。Jobs可以做成标准的Java组件或 EJBs。Quartz的最新版本为Quartz 2.2.2。下面将介绍两种Quartz使用方式:

2.3.2 使用方法

第一种:作业类继承自特定的基类
org.springframework.scheduling.quartz.QuartzJobBean
①编写作业类

import org.quartz.JobExecutionContext;  
import org.quartz.JobExecutionException;  
import org.springframework.scheduling.quartz.QuartzJobBean;  
public class Job1 extends QuartzJobBean {  

    private int timeout;  
    private static int i = 0;  
    //调度工厂实例化后,经过timeout时间开始执行调度  
    public void setTimeout(int timeout) {  
        this.timeout = timeout;  
    }  

    /** 
    * 要调度的具体任务 
    */  
    @Override  
    protected void executeInternal(JobExecutionContext context) throws JobExecutionException {  
          System.out.println("定时任务执行中…");  
    }  
}

②spring配置文件中配置作业类JobDetailBean

<bean name="job1" class="org.springframework.scheduling.quartz.JobDetailBean">  
    <property name="jobClass" value="com.gy.Job1" />  
    <property name="jobDataAsMap">  
        <map>  
            <entry key="timeout" value="0" />  
        </map>  
    </property>  
</bean> 

说明:org.springframework.scheduling.quartz.JobDetailBean有两个属性,jobClass属性即我们在java代码中定义的任务类,jobDataAsMap属性即该任务类中需要注入的属性值。

③配置作业调度的触发方式(触发器)
Quartz的作业触发器有两种,分别是
org.springframework.scheduling.quartz.SimpleTriggerBean
org.springframework.scheduling.quartz.CronTriggerBean
第一种SimpleTriggerBean,只支持按照一定频度调用任务,如每隔30分钟运行一次。
配置方式如下:

<bean id="simpleTrigger" class="org.springframework.scheduling.quartz.SimpleTriggerBean">  
    <property name="jobDetail" ref="job1" />  
    <!-- 调度工厂实例化后,经过0秒开始执行调度 -->
    <property name="startDelay" value="0" />  
    <!-- 每2秒调度一次 --> 
    <property name="repeatInterval" value="2000" /> 
</bean> 

第二种CronTriggerBean,支持到指定时间运行一次,如每天12:00运行一次等。
配置方式如下:

<bean id="cronTrigger" class="org.springframework.scheduling.quartz.CronTriggerBean">  
    <property name="jobDetail" ref="job1" />  
    <!—每天12:00运行一次 -->  
    <property name="cronExpression" value="0 0 12 * * ?" />  
</bean> 

④配置调度工厂

<bean class="org.springframework.scheduling.quartz.SchedulerFactoryBean">  
    <property name="triggers">  
        <list>  
            <ref bean="cronTrigger" />  
        </list>  
    </property>  
</bean> 

说明:该参数指定的就是之前配置的触发器的名字。

⑤启动你的应用即可,即将工程部署至tomcat或其他容器。

第二种:作业类不继承特定基类(推荐使用)
Spring能够支持这种方式,归功于两个类:
org.springframework.scheduling.timer.MethodInvokingTimerTaskFactoryBean
org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean
这两个类分别对应spring支持的两种实现任务调度的方式,即前文提到到java自带的timer task方式和Quartz方式。这里我只写MethodInvokingJobDetailFactoryBean的用法,使用该类的好处是,我们的任务类不再需要继承自任何类,而是普通的pojo。
①编写作业类(普通POJO)

public class Job2 {  
public void doJob2() {  
    System.out.println("不继承QuartzJobBean方式-调度进行中...");  
    }  
}  

②配置作业类

<bean id="job2"  
class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">  
    <property name="targetObject">  
        <bean class="com.gy.Job2" />  
    </property>  
    <property name="targetMethod" value="doJob2" />  
    <!-- 作业不并发调度 -->  
    <property name="concurrent" value="false" />
</bean> 

说明:这一步是关键步骤,声明一个MethodInvokingJobDetailFactoryBean,有两个关键属性:targetObject指定任务类,targetMethod指定运行的方法。

③配置作业调度的触发方式(触发器)
Quartz的作业触发器有两种,分别是
org.springframework.scheduling.quartz.SimpleTriggerBean
org.springframework.scheduling.quartz.CronTriggerBean
第一种SimpleTriggerBean,只支持按照一定频度调用任务,如每隔30分钟运行一次。
配置方式如下:

<bean id="simpleTrigger" class="org.springframework.scheduling.quartz.SimpleTriggerBean">  
    <property name="jobDetail" ref="job1" />
    <!-- 调度工厂实例化后,经过0秒开始执行调度 -->    
    <property name="startDelay" value="0" />
    <!-- 每2秒调度一次 -->  
    <property name="repeatInterval" value="2000" />
</bean> 

第二种CronTriggerBean,支持到指定时间运行一次,如每天12:00运行一次等。
配置方式如下:

<bean id="cronTrigger" class="org.springframework.scheduling.quartz.CronTriggerBean">  
    <property name="jobDetail" ref="job1" />  
    <!—每天12:00运行一次 -->  
    <property name="cronExpression" value="0 0 12 * * ?" />  
</bean> 

④配置调度工厂

<bean class="org.springframework.scheduling.quartz.SchedulerFactoryBean">  
    <property name="triggers">  
        <list>  
            <ref bean="cronTrigger" />  
        </list>  
    </property>  
</bean>

说明:该参数指定的就是之前配置的触发器的名字。
⑤启动你的应用即可,即将工程部署至tomcat或其他容器。

2.2.3 扩展内容

①配置多个定时器任务

<util:properties id="applicationProps" location="classpath:enroll.properties" />
    <context:property-placeholder properties-ref="applicationProps" />

    <bean id="waitListExpireJob" class="com.yunteng.ngtl.enroll.tool.waitListExpireTaskJob" />
    <bean id="expireJobTask"
        class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">
        <property name="targetObject" ref="waitListExpireJob" />
        <property name="targetMethod" value="expireProcess" />
    </bean>
    <bean id="waitListExpireTrigger" class="org.springframework.scheduling.quartz.CronTriggerBean">
        <property name="name" value="waitListExpireTriggerName" />
        <property name="group" value="waitListExpireTriggerGroup" />
        <property name="jobDetail">
            <ref bean="expireJobTask" />
        </property>
        <property name="cronExpression">
            <value>#{applicationProps['cron.expireTask']}</value>
        </property>
    </bean>

    <bean id="waitListObserveJob" class="com.yunteng.ngtl.enroll.tool.waitListObserveTaskJob" />
    <bean id="observeJobTask"
        class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">
        <property name="targetObject" ref="waitListObserveJob" />
        <property name="targetMethod" value="observeProcess" />
    </bean>
    <bean id="waitListObserveTrigger" class="org.springframework.scheduling.quartz.CronTriggerBean">
        <property name="name" value="waitListObserveTriggerName" />
        <property name="group" value="waitListObserveTriggerGroup" />
        <property name="jobDetail">
            <ref bean="observeJobTask" />
        </property>
        <property name="cronExpression">
            <value>#{applicationProps['cron.observeTask']}</value>
        </property>
    </bean>

    <bean class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
       <property name="triggers">
         <list>
           <ref local="waitListExpireTrigger" />
           <ref local="waitListObserveTrigger" />
         </list>
       </property>
     </bean>

②动态修改定时器任务调度时间周期(关键字:quartz change cron expression runtime)
注意:目前只在Quartz1.8.6版本下测试成功

CronTrigger cronTrigger = (CronTrigger) stdScheduler.getTrigger(triggerName,triggerGroupName);
cronTrigger.setCronExpression(newCronExpression);
stdScheduler.rescheduleJob(triggerName,triggerGroupName,cronTrigger);

3 总结与分析

~ Timer Spring-Task Quartz
作业类的继承方式 java.util.Timer中需要继承自java.util.TimerTask 普通的java类,不需要继承其他类 继承自org.springframework.scheduling.quartz.QuartzJobBean
是否可以使用Cron表达式 不可以 可以 可以
动态改变执行时间周期 可以,但是使用不灵活 资料太少,未找到相关方法 可以,将触发器重新启动即可重新调度任务(资料较多,目前只在Quartz1.8.6版本测试通过)
使用难易程度 简单 简单 稍难,需要配置的部分相对较多且繁琐

这篇博文到这里就结束了,希望下次有时间可以多添加一些图表等更加形象的内容。

版权声明:本文为博主原创文章,未经博主允许不得转载。

相关文章推荐

【Spring】定时任务详解实例-@Scheduled

转载请注明出处:http://blog.csdn.net/qq_26525215 本文源自【大学之旅_谙忆的博客】 最近在做项目,时间比较紧张,也有比较久没写博客了。 现在项目的Redis缓存需要用...

定时任务实现方式总结

java timer  实现定时任务 web 应用  利用servlet或listenter 来启动定时任务 1. servlet package com.rc.portal.webapp.ac...

详解java定时任务

在我们编程过程中如果需要执行一些简单的定时任务,无须做复杂的控制,我们可以考虑使用JDK中的Timer定时任务来实现。下面LZ就其原理、实例以及Timer缺陷三个方面来解析java Timer定时器。...

一个Main测试的Spring+Quartz配置动态定时任务的方法

首先参考文章http://sulaohuai.blog.51cto.com/10674946/1702625里面的示例写的不是太全,自己揣测大致补全了代码,亲测可用。1、Main方法的测试类packa...

openstack中运行定时任务的两种方法及源代码分析

启动一个进程,如要想要这个进程的某个方法定时得进行执行的话,在openstack有两种方式: 一种是通过继承 periodic_task.PeriodicTasks,另一种是使用loopingcall...

Linux定时任务Crontab的使用方法总结

一、crond简介 crond是linux下用来周期性的执行某种任务或等待处理某些事件的一个守护进程,与windows下的计划任务类似 查看系统任务调度的配置文件 [root@localhost]# ...

Java实现定时任务的三种方法

在应用里经常都有用到在后台跑定时任务的需求。举个例子,比如需要在服务后台跑一个定时任务来进行垃圾回收(译者注:个人觉得用定时任务来跑垃圾回收不是很好的例子,从译者接触到的项目来看,比较常见的是用定时任...
  • Baple
  • Baple
  • 2014-04-10 08:45
  • 1289

php定时计划任务实现方法

我在uchome 中 分析到, uchome是这样做的    1. 把所有的计划任务存放到数据库    2. 每次用户进行操作或打开页面的时候都按排序执行一条计划任务. 也就是轮番判断,时间到了的...

Android中定时执行任务的3种实现方法

在Android开发中,定时执行任务的3种实现方法: 一、采用Handler与线程的sleep(long)方法(不建议使用,java的实现方式) 二、采用Handler的postDelayed...

Spring+Quartz实现定时任务的配置方法

1、Scheduler的配置 ...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:深度学习:神经网络中的前向传播和反向传播算法推导
举报原因:
原因补充:

(最多只允许输入30个字)