本人小菜一个,第一次写博文,作为自己的一个知识总结,有什么不对的地方,还请大家多多指教。
最近项目中需要实现定时调用任务处理,以前看到spring中内置了定时任务的实现,于是便自己动手写了个demo,代码如下:
spring的配置文件:
<span style="font-family:Microsoft YaHei;font-size:14px;"><span style="font-size:18px;"><?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:p="http://www.springframework.org/schema/p"
xmlns:dwr="http://www.directwebremoting.org/schema/spring-dwr"
xmlns:task="http://www.springframework.org/schema/task"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
http://www.directwebremoting.org/schema/spring-dwr
http://www.directwebremoting.org/schema/spring-dwr-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.1.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd">
<!-- 定时任务的工作Bean -->
<bean id="quartzJob" class="com.tigo.it.action.TaskServiceImpl" />
<!-- 定义生成工作对象的工厂,并为工厂设定目标对象targetObject属性、目标对象的工作方法targetMethod属性 -->
<bean id="jobDetail" class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">
<property name="targetObject" ref="quartzJob" />
<property name="targetMethod">
<value>synchronizeDb</value>
</property>
<property name="concurrent" value="true" />
</bean>
<!--为了查看多个定时任务之间的运行,定义了2个任务-->
<bean id="jobDetail1" class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">
<property name="targetObject" ref="quartzJob" />
<property name="targetMethod">
<value>synchronizeDb2</value>
</property></span>
<span style="font-family:Microsoft YaHei;font-size:14px;"> <!--多线程执行定时任务,false则为单线程 --></span>
<span style="font-family: 'Microsoft YaHei'; "><span style="font-size:14px;"> <property name="concurrent" value="true" /> </span></span>
<span style="font-family:Microsoft YaHei;font-size:14px;"> </bean>
<!-- 任务调度计时器,进行定时设置。CronTriggerBean能进行非常精确的定时设置 -->
<bean id="cronQuartzClock" class="org.springframework.scheduling.quartz.CronTriggerBean">
<property name="jobDetail" ref="jobDetail" />
<!-- cron表达式 -->
<property name="cronExpression">
<value>0/10 * * * * ?</value>
</property>
</bean>
<bean id="cronQuartzClock1" class="org.springframework.scheduling.quartz.CronTriggerBean">
<property name="jobDetail" ref="jobDetail1" />
<!-- cron表达式 -->
<property name="cronExpression">
<value>0/11 * * * * ?</value>
</property>
</bean>
<!-- 调度任务触发器,启动定时任务-->
<bean class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
<property name="triggers">
<list>
<ref bean="cronQuartzClock" />
<ref bean="cronQuartzClock1" />
</list>
</property>
</bean>
</beans></span>
<span style="font-family:Microsoft YaHei;font-size:14px;">package com.tigo.it.action;</span><span style="font-family:Microsoft YaHei;font-size:18px;">
</span><span style="font-family:Microsoft YaHei;font-size:14px;">import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import javax.annotation.Resource;
import javax.mail.MessagingException;
import javax.mail.internet.MimeMessage;
import org.springframework.mail.javamail.JavaMailSenderImpl;
import org.springframework.mail.javamail.MimeMessageHelper;
import org.springframework.stereotype.Controller;
import org.springframework.stereotype.Service;
public class TaskServiceImpl {
<span style="white-space: pre; "> </span>public void synchronizeDb() {
<span style="white-space: pre; "> </span>//当前时间作为每一个线程所执行的方法的标志
Long a=System.currentTimeMillis();
<span style="white-space: pre; "> </span>System.out.println(a+":任务调度1开始!");
<span style="white-space: pre; "> </span>common("synchronizeDb",a);
<span style="white-space: pre; "> </span>System.out.println(a+":任务调度1结束!");
<span style="white-space: pre; "> </span>}
<span style="white-space: pre; "> </span>public void common(String method,Long time) {
<span style="white-space: pre; "> </span>for (int i = 0; i <10; i++) {
<span style="white-space: pre; "> </span>try {
<span style="white-space: pre; "> </span>Thread.sleep(1000);
<span style="white-space: pre; "> </span>System.out.println(i+":当前执行的方法为:"+method+",时间标志为:"+time);
<span style="white-space: pre; "> </span>} catch (InterruptedException e) {
<span style="white-space: pre; "> </span>e.printStackTrace();
<span style="white-space: pre; "> </span>}
<span style="white-space: pre; "> </span>}
<span style="white-space: pre; "> </span>public void synchronizeDb2() {
Long b=System.currentTimeMillis();
<span style="white-space: pre; "> </span> System.out.println(b+":任务调度2开始!");
<span style="white-space: pre; "> </span> common("synchronizeDb2",b);
<span style="white-space: pre; "> </span> System.out.println(b+":任务调度2结束!");
<span style="white-space: pre; "> </span>}
}</span>
控制台输出结果为:
<span style="font-family:Microsoft YaHei;font-size:14px;">1414074080030:任务调度1开始!
0:当前执行的方法为:synchronizeDb,时间标志为:1414074080030
1414074082004:任务调度2开始!
1:当前执行的方法为:synchronizeDb,时间标志为:1414074080030
0:当前执行的方法为:synchronizeDb2,时间标志为:1414074082004
2:当前执行的方法为:synchronizeDb,时间标志为:1414074080030
1:当前执行的方法为:synchronizeDb2,时间标志为:1414074082004
3:当前执行的方法为:synchronizeDb,时间标志为:1414074080030
2:当前执行的方法为:synchronizeDb2,时间标志为:1414074082004
4:当前执行的方法为:synchronizeDb,时间标志为:1414074080030
3:当前执行的方法为:synchronizeDb2,时间标志为:1414074082004
5:当前执行的方法为:synchronizeDb,时间标志为:1414074080030
4:当前执行的方法为:synchronizeDb2,时间标志为:1414074082004
6:当前执行的方法为:synchronizeDb,时间标志为:1414074080030
5:当前执行的方法为:synchronizeDb2,时间标志为:1414074082004
7:当前执行的方法为:synchronizeDb,时间标志为:1414074080030
6:当前执行的方法为:synchronizeDb2,时间标志为:1414074082004
8:当前执行的方法为:synchronizeDb,时间标志为:1414074080030
7:当前执行的方法为:synchronizeDb2,时间标志为:1414074082004
1414074090005:任务调度1开始!
9:当前执行的方法为:synchronizeDb,时间标志为:1414074080030
1414074080030:任务调度1结束!
8:当前执行的方法为:synchronizeDb2,时间标志为:1414074082004
0:当前执行的方法为:synchronizeDb,时间标志为:1414074090005
1:当前执行的方法为:synchronizeDb,时间标志为:1414074090005
9:当前执行的方法为:synchronizeDb2,时间标志为:1414074082004
1414074082004:任务调度2结束!</span>
结论:
一、在上面配置条件下(多线程)
1、对于同一个定时任务:当10秒的任务第一次开启后,若在10秒内完成,则第20秒正常启动;若10秒未完成,第 20秒会新开一个线程执行,原来的线程继续执行。
2、对于不同的定时任务:与同一个任务一致,互不影响,采用不同的线程各自执行。
二、单线程环境下(大家可自行测试)
1、无论任务有多少,都只会有一个线程在执行,以上面为例,当10秒的任务第一次开启后,若在10秒内完成,则第 20秒继续执行新的任务(新的任务可以是10秒间隔的,也可以是11秒间隔的);若第10秒还未完成,则等待此 任务执行完毕才开始新的任务。