最近项目中用到了定时任务,以前没有接触过,在此对java中定时任务的实现进行总结。
实现定时任务的方式有2种,一种是使用java类库中的java.util.Timer;另一种是使用quartz框架。
Timer只能实现简单的任务调度,quartz可以满足各种复杂的任务调度时间需求。
1、Timer的实现方式
在Timer中存在一个任务(Task)的概念,通过继承java.util.TimerTask实现,代码如下:
public class MyTask extends TimerTask{
@Override
public void run() {
System.out.println("execute my task!");
}
}
然后使用Timer实例实现任务的触发和调度,代码如下:
public class MyTimer {
public static void main(String[] args) {
Timer timer= new Timer();
// 1秒钟后开始第一次,以后每隔2秒执行一次
timer.schedule(new MyTask(), 1000, 2000);
}
}
Timer的定时任务实现就这么简单。
原理:
1)通过源码可知Timer使用队列(TaskQueue)和线程(TimerThread)实现任务的调度;
2)使用Wait-Notify机制实现队列的阻塞操作;
2、quartz实现方式
Quartz 是个开源的作业调度框架,为java应用程序的作业调度提供了简单却强大的机制。
在quartz中存在一下几个概念:
1)job,相当于timer的task;
2)Trigger(触发器),用来执行job
3)Scheduler(调度器),用来管理Trigger
下面是一个简单例子:
public class SimpleJob implements Job {
@Override
public void execute(JobExecutionContext context) throws JobExecutionException {
//获取jobDetail
JobDetail jobDetail = context.getJobDetail();
// 获取jobName
String jobName = jobDetail.getName();
//获取JobDataMap
JobDataMap dataMap = jobDetail.getJobDataMap();
//JobDataMap中获取用户传入的参数
int index = dataMap.getInt("index");
//具体JOB要做的事
for(int i =0;i<index;i++){
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
}
System.out.println("simple job name:"+jobName+" ;turn "+i);
}
}
}
public class QuartzTest {
public static void main(String[] args) {
try {
// 1、创建一个任务调度器
Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler();
//2、创建一个作业
JobDetail jobDetail = new JobDetail("simpleJob", Scheduler.DEFAULT_GROUP,
SimpleJob.class);
// 2.1、JobDataMap里面加入需要的参数
jobDetail.getJobDataMap().put("index", 5);
//3、创建触发器,每8秒触发一次
Trigger trigger = TriggerUtils.makeSecondlyTrigger(8);
trigger.setName("simpleTrigger");
//3.1、开始触发时间
trigger.setStartTime(new Date());
// 4、把作业和触发器
scheduler.scheduleJob(jobDetail, trigger);
// 5、启动调度器
scheduler.start();
// 6、关闭调度器
scheduler.shutdown();
} catch (SchedulerException se) {
se.printStackTrace();
}
}
}
其中JobExecutionContext是quartz提供的一个上下文,从中可以获取job、trigger的信息;
quartz还有许多其他特性,例如job持久化、properties配置文件等,详细可参考最后的链接。
3、spring实现方式
spring对Java的Timer类和Quartz都提供了一个抽象层,使用我们可以更方便地使用它们。
1)spring对Timer的集成
<?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"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd"
default-autowire="byName">
<bean id="timer" class="org.springframework.scheduling.timer.TimerFactoryBean">
<property name="scheduledTimerTasks">
<list>
<ref local="schedule" />
</list>
</property>
</bean>
<bean id="schedule" class="org.springframework.scheduling.timer.ScheduledTimerTask">
<property name="timerTask">
<ref bean="myTask" />
</property>
<property name="delay">
<value>1000</value>
</property>
<property name="period">
<value>1000</value>
</property>
</bean>
<bean id="myTask" class="com.test.MyTask" />
</beans>
2)spring对quartz的集成
<?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"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd"
default-autowire="byName">
<bean id="myTask" class="com.test.MyTask" />
<!-- jobDetail -->
<bean id="quartzJobDetail" class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">
<property name="targetObject" ref="myTask" />
<property name="targetMethod" value="run" />
<property name="concurrent" value="false" />
</bean>
<!-- trigger -->
<bean id="quartzTrigger" class="org.springframework.scheduling.quartz.CronTriggerBean">
<property name="jobDetail" ref="quartzJobDetail" />
<property name="cronExpression" value="0/3 * * * * ?"/>
</bean>
<!-- schdule -->
<bean id="quertzSchdule" lazy-init="false" autowire="no" class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
<property name="triggers">
<list>
<ref bean="quartzTrigger" />
</list>
</property>
</bean>
</beans>
在spring容器加载配置文件中的bean后,任务调度就会开始。
参考: